/****************************************************************************
*
*  ALi (Shanghai) Corporation, All Rights Reserved. 2003 Copyright (C)
*
*  File: win_upgrade_menu.c
*
*  Description: 
*              
*  History:
*      Date        	         Author             	Version     	        Comment
*      ====        	======        	=======   	=======
*      6/27/2007       Shine Zhou	 0.1.0.0             Build for USB upgrade
****************************************************************************/
#include <sys_config.h>
#ifdef USB_MP_SUPPORT
#include <types.h>
#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <osal/osal.h>
#include <hld/pan/pan_dev.h>
#include <hld/pan/pan.h>

#include <api/libosd/osd_lib.h>
#include <api/libchunk/chunk.h>
#include <api/libupg/usb_upgrade.h>

#ifdef DISK_MANAGER_SUPPORT
#include <api/libfs2/statvfs.h>
#endif

#include "osdobjs_def.h"
#include "win_com_popup.h"
#include "string.id"
#include "images.id"
#include "osd_config.h"
#include "osd_rsc.h"
//#include "control.h"
#include "win_com.h"

#ifdef _CAS9_CA_ENABLE_
#include <hld/crypto/crypto.h>
#endif

#include "menus_root.h" //by_blushark
//#include "win_com_menu_define.h"
#include <api/librsa/rsa_verify.h>

#ifdef _VMX_CA_ENABLE_
#include <hld/crypto/crypto.h>
#include <api/libcas/vmx/bc_types.h>

#ifdef FAKE_VERITY_SIGNATURE
	#define BC_VerifySignature  FakeBC_VerifySignature
#endif
#endif

#define USBUPG_ONLY_ALLCODE //ChengYu@20140507, only AllCode upgrage mode
#if 1
#define UU_PRINTF(...)
#else
#define UU_PRINTF libc_printf
#define UU_DUMP(data, len) \
	do { \
		int i, l = (len); \
		for (i = 0; i < l; i++) \
			UU_PRINTF(" 0x%02x", *((data) + i)); \
		UU_PRINTF("\n"); \
	} while (0)
#endif
#define ZIP7_HEAD_EASY				0x8000006c
#define MAINCODE_ZIP_HEAD  		    ZIP7_HEAD_EASY

#if (defined _CAS9_CA_ENABLE_) && (defined _M3503_)
#define BACKUP_USB_LOADER
#define READ_USBUPG_BUFFER_SIZE 0xA00000	/* 10M */
#define SEE_CODE  1
#define MAIN_CODE 0
#endif

/*******************************************************************************
* Objects declaration
*******************************************************************************/
#define USBUPG_FILE_BUFFER_ADDR 0x80800000
#define USBUPG_CHUNK_NAME_LEN (16 +1)
#if Maker_GUI_ON
#define USBUPG_MSG_MAX_LINE 3
#else
#define USBUPG_MSG_MAX_LINE 5
#endif

extern CONTAINER win_usbupg_con;

extern CONTAINER usbupg_item_con1;
extern CONTAINER usbupg_item_con2;
extern CONTAINER usbupg_item_con3;

extern TEXT_FIELD usbupg_txt_upgrade_type;
extern TEXT_FIELD usbupg_txt_file_select;
extern TEXT_FIELD usbupg_txt_start;

extern MULTISEL	usbupg_sel_upgrade_type;
extern MULTISEL usbupg_filelist_sel;

extern CONTAINER usbupg_info_con;
extern TEXT_FIELD usbupg_txt_progress;
extern PROGRESS_BAR usbupg_bar_progress;
extern TEXT_FIELD usbupg_txt_msg;
extern TEXT_FIELD usbupg_item_line0;
extern TEXT_FIELD usbupg_item_line1;
extern TEXT_FIELD usbupg_item_line2;

static VACTION usbupg_item_sel_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT usbupg_item_sel_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

static VACTION usbupg_item_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT usbupg_item_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

static VACTION usbupg_con_keymap(POBJECT_HEAD pObj, UINT32 key);
static PRESULT usbupg_con_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2);

UINT16 usbupg_blocks_cnt,usbupg_files_cnt;
//static UINT16 *usbupg_msg_buf[USBUPG_MSG_MAX_LINE+1];
static UINT16 usbupg_msg_buf[USBUPG_MSG_MAX_LINE+1];
static UINT32 usbupg_msg_line ;

static PRESULT win_usbupg_init(void);

UINT8 aov_fast_usbupg_start_proc(USBUPG_BLOCK_TYPE block_type);//ChengYu@20140221, for fast upgrade
#ifdef _BUILD_USB_LOADER_
#define WIN_SH_IDX	  	WSTL_WINSEARCH_03_HD
#else
#define WIN_SH_IDX	 WSTL_WIN_BODYRIGHT_01_HD
#endif
#define CON_SH_IDX	WSTL_BUTTON_01_HD
#define CON_HL_IDX	WSTL_BUTTON_05_HD
#define CON_HL1_IDX	WSTL_BUTTON_05_HD//WSTL_BUTTON_02
#define CON_SL_IDX	WSTL_BUTTON_01_HD
#define CON_GRY_IDX	WSTL_BUTTON_07_HD

#define TXTN_SH_IDX   WSTL_BUTTON_01_FG_HD
#define TXTN_HL_IDX   WSTL_BUTTON_02_FG_HD
#define TXTN_SL_IDX   WSTL_BUTTON_02_FG_HD
#define TXTN_GRY_IDX  WSTL_BUTTON_07_HD

#define TXTS_SH_IDX   WSTL_BUTTON_01_HD //WSTL_BUTTON_01_FG_HD
#define TXTS_HL_IDX   WSTL_BUTTON_04_HD
#define TXTS_SL_IDX   WSTL_BUTTON_01_FG_HD
#define TXTS_GRY_IDX  WSTL_BUTTON_07_HD

#define USBUPG_INFO_SH_IDX	WSTL_TEXT_09_HD


#define PROGRESSBAR_SH_IDX			WSTL_BARBG_01_HD
#define PROGRESSBAR_MID_SH_IDX		WSTL_NOSHOW_IDX
#define PROGRESSBAR_PROGRESS_SH_IDX	WSTL_BAR_04_HD

#define B_MID_SH_IDX                WSTL_NOSHOW_IDX

#define PROGRESS_TXT_SH_IDX	WSTL_BUTTON_01_HD

#ifdef SD_UI
#ifdef	_BUILD_USB_LOADER_
#define	W_W     482//500
#define	W_H     380
#define	W_L     GET_MID_L(W_W)
#define	W_T     60//80
#else
#define	W_L     	105//248//384
#define	W_T     	57//98//138
#define	W_W     	482//692
#define	W_H     	370//488
#endif
#define CON_L		(W_L+20)
#define CON_T		(W_T + 8)
#define CON_W		(W_W - 40)
#define CON_H		30//40
#define CON_GAP		8//12

#define TXTN_L_OF  	10//4
#define TXTN_W  	180//240//200
#define TXTN_H		30//40
#define TXTN_T_OF	((CON_H - TXTN_H)/2)

#define TXTS_L_OF  	(TXTN_L_OF + TXTN_W)
#define TXTS_W  	(CON_W - TXTN_W - 20)
#define TXTS_H		30//40//28
#define TXTS_T_OF	((CON_H - TXTS_H)/2)

#define MSG_SH_IDX WSTL_TEXT_09_HD//sharon WSTL_TEXT_04_HD

#define BAR_L	(CON_L+5)
#define BAR_T	(CON_T + (CON_H + CON_GAP)*3+10)
#define BAR_W	(CON_W-BAR_TXT_W-10)
#define BAR_H	16//24

#define BAR_TXT_L (BAR_L + BAR_W + 6)
#define BAR_TXT_W	100//sharon 60
#define BAR_TXT_T ( BAR_T - 6)
#define BAR_TXT_H	36//24 

#define MSG_L	(CON_L+5)
#define MSG_T	(BAR_T + BAR_H+20)
#define MSG_W	(CON_W-10)
#define MSG_H	30//40
#define MSG_GAP	4

#define UPG_MODE_ID 1
#define UPG_FILE_ID 2
#define START_ID    3

#define LINE_L_OF	0
#define LINE_T_OF  	(CON_H+4)
#define LINE_W		CON_W
#define LINE_H     	4
#else
#if Maker_GUI_ON
#ifdef	_BUILD_USB_LOADER_
#define	W_W     Maker_GUI_SM_W//493
#define	W_H     Maker_GUI_SM_H//320
#define	W_L     Maker_GUI_SM_L//60
#define	W_T     Maker_GUI_SM_T//GET_MID_T(W_H)//60	
#else
#define	W_L     	Maker_GUI_SM_L
#define	W_T     	Maker_GUI_SM_T
#define	W_W     	Maker_GUI_SM_W
#define	W_H     	Maker_GUI_SM_H
#endif
#else
#ifdef	_BUILD_USB_LOADER_
#define	W_W     692//493
#define	W_H     488//320
#define	W_L     GET_MID_L(W_W)//60
#define	W_T     98//GET_MID_T(W_H)//60	
#else
#define	W_L     	248
#define	W_T     	98
#define	W_W     	692
#define	W_H     	488
#endif
#endif

#define CON_L		(W_L+20)
#if Maker_GUI_ON
#define CON_T		(W_T)
#else
#define CON_T		(W_T + 4)
#endif
#define CON_W		(W_W - 60)
#define CON_H		40
#define CON_GAP		12

#define TXTN_L_OF  	4
#define TXTN_W  	240//200
#define TXTN_H		40
#define TXTN_T_OF	((CON_H - TXTN_H)/2)

#define TXTS_L_OF  	(TXTN_L_OF + TXTN_W)
#define TXTS_W  	(CON_W - TXTN_W - 20)
#define TXTS_H		40//28
#define TXTS_T_OF	((CON_H - TXTS_H)/2)

#define MSG_SH_IDX WSTL_TEXT_09_HD//sharon WSTL_TEXT_04_HD

#define BAR_L	(CON_L+5)
#define BAR_T	(CON_T + (CON_H + CON_GAP)*3+14)
#define BAR_W	(CON_W-BAR_TXT_W-10)
#define BAR_H	24

#define BAR_TXT_L (BAR_L + BAR_W + 6)
#define BAR_TXT_W	100//sharon 60
#define BAR_TXT_T ( BAR_T - 6)
#define BAR_TXT_H	36//24 

#define MSG_L	(CON_L+5)
#if Maker_GUI_ON
#define MSG_T	(BAR_T + BAR_H)
#else
#define MSG_T	(BAR_T + BAR_H+20)
#endif
#define MSG_W	(CON_W-10)
#define MSG_H	40
#define MSG_GAP	4

#define UPG_MODE_ID 1
#define UPG_FILE_ID 2
#define START_ID    3

#define LINE_L_OF	0
#define LINE_T_OF  	(CON_H+4)
#define LINE_W		CON_W
#define LINE_H     	4
#endif

#ifdef USBUPG_ONLY_ALLCODE
#define WINUSB_DFT_FOCUS_ID         START_ID
#define WINUSB_FILE_ID_UP           START_ID
#define WINUSB_START_ID_DOWN        UPG_FILE_ID
#else
#define WINUSB_DFT_FOCUS_ID         UPG_MODE_ID
#define WINUSB_FILE_ID_UP           UPG_MODE_ID
#define WINUSB_START_ID_DOWN        UPG_MODE_ID
#endif

#define LDEF_CON(root, varCon,nxtObj,ID,IDl,IDr,IDu,IDd,l,t,w,h,hl,conobj,focusID)		\
    DEF_CONTAINER(varCon,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,IDl,IDr,IDu,IDd, l,t,w,h, CON_SH_IDX,hl,CON_SL_IDX,CON_GRY_IDX,   \
    usbupg_item_keymap,usbupg_item_callback,  \
    conobj, ID,1)
    
#define LDEF_TXT(root,varTxt,nxtObj,l,t,w,h,resID)		\
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, TXTN_SH_IDX,TXTN_HL_IDX,TXTN_SL_IDX,TXTN_GRY_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,resID,NULL)

#define LDEF_TXT1(root,varTxt,nxtObj,l,t,w,h,resID)		\
    DEF_TEXTFIELD(varTxt,root,nxtObj,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, TXTN_SH_IDX,CON_HL1_IDX,TXTN_SL_IDX,TXTN_GRY_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,resID,NULL)

#define LDEF_MSEL(root, varNum, nxtObj, ID, l, t, w, h,style,cur,cnt,ptabl)	\
    DEF_MULTISEL(varNum,root,nxtObj,C_ATTR_ACTIVE,0, \
    ID,ID,ID,ID,ID, l,t,w,h, TXTS_SH_IDX,TXTS_HL_IDX,TXTS_SL_IDX,TXTS_GRY_IDX,   \
    usbupg_item_sel_keymap,usbupg_item_sel_callback,  \
    C_ALIGN_CENTER | C_ALIGN_VCENTER, 20,0,style,ptabl,cur,cnt)

#if Maker_GUI_OFF
#define LDEF_PROGRESS_BAR(root,varBar,nxtObj,l,t,w,h,style,rl,rt,rw,rh)	\
	DEF_PROGRESSBAR(varBar, &root, nxtObj, C_ATTR_ACTIVE, 0, \
		0, 0, 0, 0, 0, l, t, w, h, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, \
		NULL, NULL, style, 0, 0, PROGRESSBAR_MID_SH_IDX, PROGRESSBAR_PROGRESS_SH_IDX, \
		rl,rt , rw, rh, 1, 100, 50, 0)
#else
#define LDEF_PROGRESS_BAR(root,varBar,nxtObj,l,t,w,h,style,rl,rt,rw,rh)	\
	DEF_PROGRESSBAR(varBar, &root, nxtObj, C_ATTR_ACTIVE, 0, \
		0, 0, 0, 0, 0, l, t, w, h, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, PROGRESSBAR_SH_IDX, \
		NULL, NULL, style, 0, 0, PROGRESSBAR_MID_SH_IDX, PROGRESSBAR_PROGRESS_SH_IDX, \
		rl,rt , rw, rh, 1, 100, 100, 0)
#endif		
   
#define LDEF_PROGRESS_TXT(root,varTxt,nxtObj,l,t,w,h)		\
    DEF_TEXTFIELD(varTxt,&root,nxtObj,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, USBUPG_INFO_SH_IDX,PROGRESS_TXT_SH_IDX,PROGRESS_TXT_SH_IDX,PROGRESS_TXT_SH_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_TOP, 5,0,0,display_strs[1])

#define LDEF_TXT_MSG(root,varTxt)		\
    DEF_TEXTFIELD(varTxt,&root,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0,  0,0,0,0, \
    MSG_SH_IDX,MSG_SH_IDX,MSG_SH_IDX,MSG_SH_IDX,   \
    NULL,NULL,  \
    C_ALIGN_LEFT | C_ALIGN_VCENTER, 0,0,0,NULL/*display_strs[0]*/)
    
#define LDEF_WIN(varCon,nxtObj,l,t,w,h,focusID)		\
    DEF_CONTAINER(varCon,NULL,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, WIN_SH_IDX,WIN_SH_IDX,WIN_SH_IDX,WIN_SH_IDX,   \
    usbupg_con_keymap,usbupg_con_callback,  \
    nxtObj, focusID,0)
    
#define LDEF_INFOCON(varCon,nxtObj,l,t,w,h)		\
    DEF_CONTAINER(varCon,NULL,NULL,C_ATTR_ACTIVE,0, \
    0,0,0,0,0, l,t,w,h, USBUPG_INFO_SH_IDX,USBUPG_INFO_SH_IDX,USBUPG_INFO_SH_IDX,USBUPG_INFO_SH_IDX,   \
    NULL,NULL,  \
    &nxtObj, 0,0)


#define LDEF_ITEM_SEL(root,varCon,nxtObj,varTxt,varNum,varLine,ID,IDu,IDd,l,t,w,h,\
						hl,resID,style,cur,cnt,ptbl) \
    LDEF_CON(&root,varCon,nxtObj,ID,ID,ID,IDu,IDd,l,t,w,h,hl,&varTxt,ID)   \
    LDEF_TXT(&varCon,varTxt,&varNum,l + TXTN_L_OF,t + TXTN_T_OF,TXTN_W,TXTN_H,resID)    \
    LDEF_MSEL(&varCon,varNum,NULL/*&varLine*/   ,ID, l + TXTS_L_OF ,t + TXTS_T_OF,TXTS_W,TXTS_H,style,cur,cnt,ptbl) \
    LDEF_LINE(&varCon,varLine,NULL,1,1,1,1,1,l + LINE_L_OF, t + LINE_T_OF,LINE_W,LINE_H,0,0)

#define LDEF_ITEM_TXT(root,varCon,nxtObj,varTxt,varLine,ID,IDu,IDd,l,t,w,h,\
						hl,resID) \
    LDEF_CON(&root,varCon,nxtObj,ID,ID,ID,IDu,IDd,l,t,w,h,hl,&varTxt,ID)   \
    LDEF_TXT1(&varCon,varTxt,NULL/*&varLine*/,l,t + TXTN_T_OF,w,TXTN_H,resID)    \
    LDEF_LINE(&varCon,varLine,NULL,1,1,1,1,1,l + LINE_L_OF, t + LINE_T_OF,LINE_W,LINE_H,0,0)     
    
LDEF_ITEM_SEL(win_usbupg_con,usbupg_item_con1,&usbupg_item_con2,usbupg_txt_upgrade_type,usbupg_sel_upgrade_type,usbupg_item_line0,\
	1,3,2,CON_L, CON_T + (CON_H + CON_GAP)*0,CON_W,CON_H,CON_HL_IDX,RS_TOOLS_UPGRADE_MODE,STRING_PROC,0,0,NULL)
LDEF_ITEM_SEL(win_usbupg_con,usbupg_item_con2,&usbupg_item_con3,usbupg_txt_file_select,usbupg_filelist_sel,usbupg_item_line1,\
	2,WINUSB_FILE_ID_UP,3,CON_L, CON_T + (CON_H + CON_GAP)*1,CON_W,CON_H,CON_HL_IDX,RS_USBUPG_UPGRADE_FILE,STRING_PROC,0,0,NULL)

LDEF_ITEM_TXT(win_usbupg_con,usbupg_item_con3,&usbupg_info_con,usbupg_txt_start,usbupg_item_line2,\
	3,2,WINUSB_START_ID_DOWN,CON_L, CON_T + (CON_H + CON_GAP)*2,CON_W,CON_H,CON_HL1_IDX,RS_COMMON_START)

LDEF_INFOCON(usbupg_info_con, usbupg_bar_progress,CON_L,CON_T + (CON_H + CON_GAP)*3, CON_W, 196)

/*Martin@20150115_progress_bar*/
//LDEF_PROGRESS_BAR(usbupg_info_con,usbupg_bar_progress,&usbupg_txt_progress,	\
	BAR_L, BAR_T, BAR_W, BAR_H, PROGRESSBAR_HORI_NORMAL | PBAR_STYLE_RECT_STYLE,2,5,BAR_W,BAR_H-10) ///// 2,5,B_W,B_H-10,0
LDEF_PROGRESS_BAR(usbupg_info_con,usbupg_bar_progress,&usbupg_txt_progress,	\
	BAR_L, BAR_T, BAR_W-22, BAR_H, PROGRESSBAR_HORI_NORMAL | PBAR_STYLE_RECT_STYLE,5,5,BAR_W-32,BAR_H-10) ///// 2,5,B_W,B_H-10,0
//LDEF_PROGRESS_TXT(usbupg_info_con, usbupg_txt_progress, NULL, \
			BAR_TXT_L, BAR_TXT_T, BAR_TXT_W, BAR_TXT_H)
LDEF_PROGRESS_TXT(usbupg_info_con, usbupg_txt_progress, NULL, \
		BAR_TXT_L - 8 , BAR_TXT_T, BAR_TXT_W, BAR_TXT_H)
//--End Martin
LDEF_TXT_MSG(usbupg_info_con,usbupg_txt_msg)

LDEF_WIN(win_usbupg_con,&usbupg_item_con1,W_L,W_T,W_W,W_H,WINUSB_DFT_FOCUS_ID)

/*******************************************************************************
*	Local functions & variables declare
*******************************************************************************/
#if (defined _CAS9_CA_ENABLE_) && (defined _M3503_)
#define LZMA_BASE_SIZE  1846
#define LZMA_LIT_SIZE   768
#define BUFFER_SIZE     ((LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (0 + 2))) * sizeof(UINT16))
extern int un7zip ( UINT8 *, UINT8 *, UINT8 * );
static UINT32 ENTRY_ADDR=0;
static UINT32 unzip_length=0;
#endif

typedef struct
{
	UINT32 compressed_addr;
	UINT32 compressed_len;
	UINT32 uncompressed_addr;
	UINT32 uncompressed_len;
	UINT32 swap_addr;
	UINT32 swap_len;

	UINT32 user_db_start_sector;
	UINT32 user_db_addr;
	UINT32 user_db_addr_offset;
	UINT32 user_db_len;
	UINT32 user_db_sectors;
	
	UINT32 usb_bin_addr;	// usb.bin address, write to userdb as second loader.
	UINT32 usb_bin_size;	// usb.bin size.
	UINT32 usb_bin_sectors;	// usb.bin sectors.
	UINT32 usb_bin_cfg_addr;
	
	UINT32 usb_fw_addr;		// received firmware address.
	UINT32 usb_fw_size; 	// received firmware size.	
	UINT32 usb_upg_addr;	// write to flash address.
	UINT32 usb_upg_size; 	// write to flash size.	
	UINT32 usb_upg_sectors; // write to flash sectors.

	UINT32 backup_db_addr;	// backup current database address
	UINT32 backup_db_size;	// backup current database size;
	UINT32 update_total_sectors;
	UINT32 update_secotrs_index;
#if defined(_VMX_CA_STD_ENABLE_) || defined(_VMX_CA_ENABLE_)
	UINT32 main_code_addr;
	UINT32 main_code_size;
	UINT32 see_code_addr;
	UINT32 see_code_size;
	UINT32 tmp_buf_addr;
	UINT32 tmp_buf_size;	
#endif
#if (defined _CAS9_CA_ENABLE_ || defined FTA_ONLY)
	UINT32 ota_loader_addr;
	UINT32 ota_loader_size;
	UINT32 usb_loader_addr;
	UINT32 usb_loader_size;
#ifdef _M3503_
	UINT32 ota_main_code_addr;
	UINT32 ota_main_code_size;
	UINT32 ota_see_code_addr;
	UINT32 ota_see_code_size;
#endif
	UINT32 main_code_addr;
	UINT32 main_code_size;
	UINT32 see_code_addr;
	UINT32 see_code_size;
	
	UINT32 cipher_buf_addr;
	UINT32 cipher_buf_size;	
	UINT32 decrypted_data_addr;
	UINT32 decrypted_data_size;
#endif
}USB_INFO, *POTA_INFO;

static USB_INFO m_usb_info;

static void win_usbupg_process_update(UINT32 process)
{

	if(process > 100)
		process = 0;

	OSD_SetProgressBarPos(&usbupg_bar_progress,(INT16)process);
	OSD_SetTextFieldContent(&usbupg_txt_progress, STRING_NUM_PERCENT, (UINT32)process);

	OSD_DrawObject( (POBJECT_HEAD)&usbupg_bar_progress, C_UPDATE_ALL);
	OSD_DrawObject( (POBJECT_HEAD)&usbupg_txt_progress, C_UPDATE_ALL);

#ifdef WATCH_DOG_SUPPORT
    dog_set_time(0, 0);
#endif
    
}

static void win_usbupg_msg_update(UINT16 str_id)
{
	UINT32 i,j;
	OSD_RECT rect;

	//ComAscStr2Uni(str, display_strs[10+usbupg_msg_line%USBUPG_MSG_MAX_LINE]);
#if 0
	for(i=0; i<USBUPG_MSG_MAX_LINE; i++)
	{
		if(usbupg_msg_line<USBUPG_MSG_MAX_LINE)
			j = i%USBUPG_MSG_MAX_LINE;
		else
			j = (usbupg_msg_line+1+i)%USBUPG_MSG_MAX_LINE;
		
		usbupg_msg_buf[i] = str_id;//display_strs[10+j];
	}
#endif
	usbupg_msg_buf[usbupg_msg_line % USBUPG_MSG_MAX_LINE] = str_id;

		//draw msg infos
	for(i=0; i<USBUPG_MSG_MAX_LINE; i++)
	{
		rect.uLeft 	= MSG_L;
		rect.uTop  	= MSG_T+(MSG_H+MSG_GAP)*i;
		rect.uWidth = MSG_W;
		rect.uHeight= MSG_H;

		OSD_SetRect2(&usbupg_txt_msg.head.frame, &rect);
		OSD_SetTextFieldContent(&usbupg_txt_msg, STRING_ID, (UINT32)usbupg_msg_buf[i]);
		OSD_DrawObject( (POBJECT_HEAD)&usbupg_txt_msg, C_UPDATE_ALL);
	}
	
	usbupg_msg_line++;
}

static void win_usbupg_msg_clear()
{
	UINT8 i;
	OSD_RECT rect;
	
	for(i=0;i<USBUPG_MSG_MAX_LINE;i++)
	{
		//ComAscStr2Uni("", display_strs[10+i]);
		usbupg_msg_buf[i] = 0;//display_strs[10+i];

		rect.uLeft 	= MSG_L;
		rect.uTop  	= MSG_T+(MSG_H+MSG_GAP)*i;
		rect.uWidth = MSG_W;
		rect.uHeight= MSG_H;

		OSD_SetRect2(&usbupg_txt_msg.head.frame, &rect);
		OSD_SetTextFieldContent(&usbupg_txt_msg, STRING_ID, (UINT32)usbupg_msg_buf[i]);
		OSD_DrawObject( (POBJECT_HEAD)&usbupg_txt_msg, C_UPDATE_ALL);
	}

 	usbupg_msg_line = 0;	
}

/*******************************************************************************
*	Window's keymap, proc and  callback
*******************************************************************************/
static VACTION usbupg_item_sel_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;
	
	switch(key)
	{
		case V_KEY_LEFT:
			act = VACT_DECREASE;
			break;
		case V_KEY_RIGHT:
			act = VACT_INCREASE;
			break;
		default:
			act = VACT_PASS;
	}

	return act;	

}

UINT32 string_to_lower(UINT8 *str)
{
    UINT32 i;
    if (str == NULL)
        return 0;
    for (i = 0; str[i]; i++)
    {
        if (str[i] >= 'A' && str[i] <= 'Z')
        {
            str[i] += 'a' - 'A';
        }
    }
    return i;
}

static PRESULT usbupg_item_sel_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
	UINT8 bID;
	UINT16 sel,block_idx,*Uni_str;
	UINT32 block_len;
	char str_buf[20];
    char str_extend[4];

//for HDCP2.0 key file's prefix name: HDCP20_XXXXX.key
#ifndef ALICAST_SUPPORT
    char str_filter[4];
#else
	char str_filter[7];
#endif

	PRESULT ret = PROC_PASS;
	USBUPG_FILENODE filenode;
	MULTISEL *pMsel;

	bID = OSD_GetObjID(pObj);
	switch(event)
	{
		case EVN_REQUEST_STRING:
			sel = param1;
			Uni_str= (UINT16*)param2; // NOTICE: Uni_str size is 32 (#define MAX_STR_LEN 32) in obj_multisel.c
			if(bID == UPG_MODE_ID)
			{
				switch(sel)
				{
					case 0:
						block_idx = 0;
						break;
					default:
						block_idx = sel + 1;
						break;
				}
#if (defined _CAS9_CA_ENABLE_) && (defined _M3503_)			
				block_idx = 0;
#endif
				usbupg_get_blockinfo(block_idx,str_buf,&block_len);
#if (defined _CAS9_CA_ENABLE_) && (defined _M3503_)
				sprintf(str_buf,"%s","System Software");
#endif
				ComAscStr2Uni(str_buf, Uni_str);
			}			
			else if(bID == UPG_FILE_ID)
			{
				if(usbupg_files_cnt == 0)
				{
    				pMsel = &usbupg_sel_upgrade_type;
    				switch(OSD_GetMultiselSel(pMsel))
    				{
    					case 0:
    						block_idx = 0;
    						break;
    					default:
    						block_idx = OSD_GetMultiselSel(pMsel)+ 1;
    				}
#if (defined _CAS9_CA_ENABLE_) && (defined _M3503_)				
					block_idx = 0;
#endif
                    usbupg_get_file_filter(block_idx, str_extend, str_filter);
                    string_to_lower(str_extend);
#ifdef USBUPG_UPGFILE_FILTER
                    string_to_lower(str_filter);
#else

#ifndef ALICAST_SUPPORT
                    str_filter[0] = 0;
#else
			//str_filter[0] = 0; //enable UPGFILE_FILTER only for HDCP 2.0 KEY
#endif	

#endif
                    sprintf(str_buf, "No File(%s*.%s)", str_filter, str_extend);
					ComAscStr2Uni(str_buf, Uni_str);
				}
				else
				{
					usbupg_get_filenode(&filenode,sel);
					filenode.upg_file_name[31] = 0;
					ComAscStr2Uni(filenode.upg_file_name, Uni_str);
					
				}
			}			
			else
			{
				ComAscStr2Uni("", Uni_str);
			}
			break;
		case EVN_POST_CHANGE:
			if(bID == 1)
			{
				sel = param1;
				switch(sel)
				{
					case 0:
						block_idx = 0;
						break;
					default:
						block_idx = sel + 1;
						break;
				}
#if (defined _CAS9_CA_ENABLE_) && (defined _M3503_)				
				block_idx = 0;
#endif
				usbupg_create_filelist(block_idx,&usbupg_files_cnt);

				pMsel = &usbupg_filelist_sel;
				OSD_SetMultiselSel(pMsel, 0);
				OSD_SetMultiselCount(pMsel, (usbupg_files_cnt));
				OSD_DrawObject((POBJECT_HEAD)pMsel,C_UPDATE_ALL);
			}
			break;
		default:
			break;
	}
	return ret;
}

static VACTION usbupg_item_keymap(POBJECT_HEAD pObj, UINT32 key)
{
	VACTION act;
	switch(key)
	{
	case V_KEY_ENTER:
	case V_KEY_RIGHT:		
		act = VACT_ENTER;
		break;
	default:
		act = VACT_PASS;
	}

	return act;
}

#ifdef _CAS9_CA_ENABLE_
#define MAIN_CODE_CHUNK_ID		0x01FE0101
#define SEE_CODE_CHUNK_ID		0x06F90101
#define	DECRPT_KEY_ID			0x22DD0100
#define DECRPT_KEY_MASK 		0xFFFF0000
#define C_SECTOR_SIZE       0x10000
#define USB_LOADER_CHUNK_ID		0x00FF0000 
static UINT32 upg_total_sectors;
static UINT32 upg_secotrs_index;
static UINT32 main_code_addr;
static UINT32 main_code_size;
static UINT32 see_code_addr;
static UINT32 see_code_size;
static UINT32 usb_loader_code_addr;
static UINT32 usb_loader_code_size;
static struct sto_device *m_StoDevice = NULL;
static UINT32 usb_loader_bin_sectors;

#ifdef _M3503_

struct usbupg_ver_info
{
	UINT32 m_f_ver;	// main code in flash version
	UINT32 m_m_ver;	// main code in memory version
	UINT32 s_f_ver;	// see code in flash version
	UINT32 s_m_ver;	// see code in memory version
	UINT32 o_f_ver;	// usb loader in flash version
	UINT32 u_m_ver;	// usb loader in memory version
};

static INT32 win_usbupg_set_memory(void)
{
	UINT32 addr;
	UINT32 len;
			
	m_usb_info.uncompressed_addr = __MM_PVR_VOB_BUFFER_ADDR;
	m_usb_info.uncompressed_len = 0x1000000;//0x600000; 
	m_usb_info.compressed_addr = m_usb_info.uncompressed_addr+m_usb_info.uncompressed_len;
	m_usb_info.compressed_len = 0x800000;//0x200000;
	m_usb_info.swap_addr = m_usb_info.compressed_addr + m_usb_info.compressed_len;
	m_usb_info.swap_len = 256*1024;
	m_usb_info.backup_db_addr = m_usb_info.compressed_addr;//m_ota_info.swap_addr+m_ota_info.swap_len;
	m_usb_info.backup_db_size = 0x200000;

	// user db address
	if(!api_get_chunk_add_len(USER_DB_ID, &addr, &len))
		return FALSE;
	m_usb_info.user_db_addr_offset = addr;//addr-m_usb_info.uncompressed_addr;
	m_usb_info.user_db_len = len;
	m_usb_info.user_db_start_sector = m_usb_info.user_db_addr_offset/C_SECTOR_SIZE;
	m_usb_info.user_db_sectors = m_usb_info.user_db_len/C_SECTOR_SIZE;

	if(m_usb_info.user_db_len%C_SECTOR_SIZE)
	{
	//	ASSERT(0);
		m_usb_info.user_db_sectors++;
	}
	
	// find the firmware position	
	m_usb_info.usb_fw_addr = m_usb_info.uncompressed_addr;
	m_usb_info.usb_fw_size = addr + len - m_usb_info.usb_fw_addr;
	//libc_printf("ota_fw_size=%x \n",m_ota_info.ota_fw_size);	
	// find ota.bin position.
	m_usb_info.usb_bin_addr = m_usb_info.usb_fw_addr + m_usb_info.usb_fw_size;
	m_usb_info.usb_bin_size = m_usb_info.uncompressed_len - m_usb_info.usb_fw_size;
	m_usb_info.usb_bin_sectors = m_usb_info.usb_bin_size/C_SECTOR_SIZE;
	if(m_usb_info.usb_bin_size % C_SECTOR_SIZE)
		m_usb_info.usb_bin_sectors++;
}


static INT32 InitStorage()
{
    m_StoDevice = (struct sto_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_STO);
    if(NULL == m_StoDevice)
    {
        UU_PRINTF("%s: can not get sto device\n", __FUNCTION__);
        return ERR_NO_DEV;
    }

    INT32 er = sto_open(m_StoDevice);
    if(SUCCESS != er)
    {
        UU_PRINTF("%s: can not open sto device\n", __FUNCTION__);
    }

	
    return er;
}

static UINT8 *expand_ram ( UINT32 addr, UINT32 len, int unzip ( UINT8 *, UINT8 *, UINT8 * ), UINT32 type )
{
	UINT8 *buffer;
	UINT8 *codeentry;
	UINT32 i = 0;

	ENTRY_ADDR=m_usb_info.swap_addr+m_usb_info.swap_len;
	
	
	//ENTRY_ADDR=usb_tmp_buf_addr;
	unzip_length = 0;

	codeentry = ( UINT8 * ) ENTRY_ADDR;

	buffer = MALLOC ( BUFFER_SIZE );
	if ( buffer == NULL )
	{
		UU_PRINTF ( "ota : No decompress buffer!\n" );
		return 0;
	}
//	libc_printf("ENTRY_ADDR = %x buffer size = %d, type = %d, addr = %d codeentry = %d\n", ENTRY_ADDR, BUFFER_SIZE, type, addr,codeentry);
	if ( unzip ( ( void * ) ( addr ), codeentry, buffer ) != 0 )
	{
		codeentry = 0;
		UU_PRINTF ( "ota : error to decompress chunk(type %d)!\n", type );
	}
	else
	{
		unzip_length = * ( UINT32* ) buffer;
	}
	osal_cache_flush(codeentry,unzip_length);
	FREE ( buffer );
	return codeentry;
}


static UINT8* usb_unzip_sw(UINT8 *decrypted, UINT32 mc_len,UINT32 type)
{
    UINT32 ziped_len = 0;
    UINT8 *p=NULL;   
    UINT8 *entry=NULL;

    p = decrypted + ( mc_len - 0x200 );
    ziped_len = p[3] | ( p[2] << 8 ) | ( p[1] << 16 ) | ( p[0] << 24 );
    UU_PRINTF ( "expand code, ziped len: 0x%x\n", ziped_len );

    entry = expand_ram ( decrypted, ziped_len, un7zip, type );
  
    return entry; 
}

static BOOL usbupg_check(struct usbupg_ver_info *ver_info,UINT8 *pbuff, UINT32 buf_len)
{
	struct sto_device *flash_dev = NULL;
	UINT8 *cipher_addr;
	UINT32 cipher_len;
	UINT8 *addr;
	UINT8 *block_addr;
	UINT32 len;
	UINT32 chunk_id = 0;
	UINT8 *data= NULL;
	UINT32 data_len = 0;
	UINT8 key_pos;
	int ret;
	CHUNK_HEADER chunk_header;	
	
	if (NULL == pbuff || 0 == buf_len)
	{
		return FALSE;
	}
	//init chunk
	chunk_init(pbuff, buf_len);
	// decrypt universal key, fetch public key from flash
	if (decrypt_universal_key(&key_pos, DECRPT_KEY_ID) < 0)
	{
		UU_PRINTF("Decrypt universal key failed!\n");
		return FALSE;
	}
	
	// get the versions of codes in flash 
	cipher_addr = pbuff + buf_len;
	cipher_len = 0x200000;
	flash_cipher_buf_init(cipher_addr, cipher_len);
	
	addr = cipher_addr + cipher_len;

	UU_PRINTF("check main code in flash\n");
	len = 0;
	ret = aes_cbc_decrypt_chunk(key_pos, MAIN_CODE_CHUNK_ID, addr, &len);
	UU_PRINTF("ret = %d, len = %d MAIN_CODE_CHUNK_ID = %x\n", ret,len,MAIN_CODE_CHUNK_ID);

	if ((ret == 0) && (len != 0)&&(usb_unzip_sw(addr, len,MAIN_CODE)!=0))
		ver_info->m_f_ver = get_code_version(ENTRY_ADDR, unzip_length);
	

	UU_PRINTF("check see code in flash\n");
	len = 0;
	ret = aes_cbc_decrypt_chunk(key_pos, SEE_CODE_CHUNK_ID, addr, &len);

	if ((ret == 0) && (len != 0)&&(usb_unzip_sw(addr, len,SEE_CODE)!=0))
		ver_info->s_f_ver = get_code_version(ENTRY_ADDR, unzip_length);


	UU_PRINTF("check usb loader in memory\n");

	chunk_id = USER_DB_ID;
	usb_loader_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if(!get_chunk_add_len(USER_DB_ID, &usb_loader_code_addr, &len)) // Got usb_loader_code_addr : add chunk header already
	{
		UU_PRINTF("cannot find user db in memory\n");
		return FALSE;
	}	

	usb_loader_code_addr = usb_loader_code_addr + len;
//	libc_printf("chunk_id = %x, usb_loader_code_addr = %x\n",chunk_id,usb_loader_code_addr);
	if (usb_loader_code_addr)
	{
		data = (UINT8 *)usb_loader_code_addr;
		
		chunk_id = USB_LOADER_CHUNK_ID;
		block_addr = (UINT8 *)usb_loader_code_addr;	

		/* Get usb loader main code offset */
		chunk_header.offset=fetch_long(block_addr + CHUNK_OFFSET);
		usb_loader_code_size = chunk_header.offset;
	//	libc_printf("loader main offset = %x\n", chunk_header.offset);

		/* Go to the next chunk , get loader see code offset */
		block_addr += chunk_header.offset;
		chunk_header.offset=fetch_long(block_addr + CHUNK_OFFSET);
		usb_loader_code_size += chunk_header.offset;
	//	libc_printf("loader see offset = %x\n", chunk_header.offset);

		/* Go to the next chunk , get loader parameter offset */
		block_addr += chunk_header.offset;
		chunk_header.offset=fetch_long(block_addr + CHUNK_OFFSET);
		usb_loader_code_size += chunk_header.offset;	
	//	libc_printf("loader parameter offset = %x\n", chunk_header.offset);
		
		data_len = fetch_long(data + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
		UU_PRINTF("\nusb_loader_code_size = %d,,data_len = %x\n",usb_loader_code_size,data_len);
		data += CHUNK_HEADER_SIZE;
			
		if ((aes_cbc_decrypt_ram_chunk(key_pos, addr, data, data_len) == 0)&&(usb_unzip_sw(addr, data_len,MAIN_CODE)!=0) )	
			ver_info->u_m_ver = get_code_version(ENTRY_ADDR, unzip_length);

	}

		

	UU_PRINTF("check main code in memory\n");
	chunk_id = MAIN_CODE_CHUNK_ID;
	main_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (main_code_addr)
	{
		data = (UINT8 *)main_code_addr;
		main_code_size = fetch_long(data + CHUNK_OFFSET);
		data_len = fetch_long(data + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
		data += CHUNK_HEADER_SIZE;
			
		if ((aes_cbc_decrypt_ram_chunk(key_pos, addr, data, data_len) == 0)&&(usb_unzip_sw(addr, data_len,MAIN_CODE)!=0) )	
			ver_info->m_m_ver = get_code_version(ENTRY_ADDR, unzip_length);

	}

	UU_PRINTF("check see code in memory\n");
	chunk_id = SEE_CODE_CHUNK_ID;
	see_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (see_code_addr)
	{
		data = (UINT8 *)see_code_addr;
		see_code_size = fetch_long(data + CHUNK_OFFSET);
		data_len = fetch_long(data + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
		data += CHUNK_HEADER_SIZE;
			
		if ((aes_cbc_decrypt_ram_chunk(key_pos, addr, data, data_len) == 0)&&(usb_unzip_sw(addr, data_len,SEE_CODE)!=0) )	
			ver_info->s_m_ver = get_code_version(ENTRY_ADDR, unzip_length);

	}

	UU_PRINTF("version info:  (0x%X, 0x%X), (0x%X, 0x%X), (usb_loader:0x%X)\n",
		ver_info->m_f_ver,ver_info->m_m_ver, ver_info->s_f_ver, ver_info->s_m_ver, ver_info->u_m_ver);

	ce_ioctl((pCE_DEVICE)dev_get_by_id(HLD_DEV_TYPE_CE, 0), IO_CRYPT_POS_SET_IDLE, key_pos);

	return TRUE;
}

static INT32 BurnBlock(UINT8 *pBuffer, UINT32 Pos, UINT8 NumSectors)
{
	struct sto_device *sto_dev = m_StoDevice;
    UINT32 param[2];
    INT32 offset, er = SUCCESS;
    UINT8 i;

    for(i=0; i<NumSectors; i++)
    {
        offset = (Pos + i) * C_SECTOR_SIZE;
        param[0] = (UINT32)offset;
        param[1] = C_SECTOR_SIZE >> 10; // length in K bytes
        UU_PRINTF("%s: erase sector %d\n", __FUNCTION__, Pos+i);
        er = sto_io_control(sto_dev, STO_DRIVER_SECTOR_ERASE_EXT, param);
        if(er != SUCCESS)
        {
            UU_PRINTF("%s: erase sector %d failed\n", __FUNCTION__, i);
            break;
        }

        if(pBuffer)
        {
            UU_PRINTF("%s: seek sector %d, offset = %xh\n", __FUNCTION__, Pos+i,offset);
            if(sto_lseek(sto_dev, offset, STO_LSEEK_SET) != offset)
            {
                UU_PRINTF("%s: seek sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }

            UU_PRINTF("%s: write sector %d, src = %xh\n", __FUNCTION__, Pos+i,&pBuffer[C_SECTOR_SIZE * i]);
            if(sto_write(sto_dev, &pBuffer[C_SECTOR_SIZE * i], C_SECTOR_SIZE) != C_SECTOR_SIZE)
            {
                UU_PRINTF("%s: write sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }
        }
	  upg_secotrs_index ++;
 	  win_usbupg_process_update(upg_secotrs_index*100/upg_total_sectors);       
    }
    return er;
}

static INT32 BackupDatabase()
{
	struct sto_device *sto_dev = m_StoDevice;
    INT32 er;

	if(sto_lseek(sto_dev, (INT32)m_usb_info.user_db_addr_offset, STO_LSEEK_SET) !=  (INT32)m_usb_info.user_db_addr_offset)
    		return ERR_FAILED;
	
	if(sto_read(sto_dev, (UINT8 *)m_usb_info.backup_db_addr, (INT32)m_usb_info.user_db_len) != (INT32)m_usb_info.user_db_len)
		return ERR_FAILED;

    return SUCCESS;
}

static BOOL win_usb_burnflash(struct usbupg_ver_info ver_info)
{
	BOOL fw_not_match = FALSE;
    	win_popup_choice_t choice;
    	UINT8 back_saved;
	struct sto_device *flash_dev = NULL;
	UINT32 chunk_id, chunk_addr, chunk_size;

	UINT32 upgrade_size = 0;
	if (ver_info.m_m_ver > ver_info.m_f_ver)
		upgrade_size += main_code_size;
	
	if (ver_info.s_m_ver > ver_info.s_f_ver)
		upgrade_size += see_code_size;
#ifndef _BUILD_OTA_E_
	if (ver_info.u_m_ver > 0)
		upgrade_size += usb_loader_code_size;
	
	if(m_usb_info.user_db_sectors)
		upgrade_size = upgrade_size + m_usb_info.user_db_sectors*C_SECTOR_SIZE;
#endif

	if (upgrade_size == 0)
	{
		win_compopup_init(WIN_POPUP_TYPE_OK);
		win_compopup_set_msg("Nothing need to be upgrade!", NULL, 0);
		win_compopup_set_default_choice(WIN_POP_CHOICE_YES);
		win_compopup_open_ext(&back_saved);
		return FALSE;
	}

	upg_total_sectors = upgrade_size / C_SECTOR_SIZE;
	upg_secotrs_index = 0;	
	InitStorage();
	
	UINT32 flash_pos;
	UINT32 ret;

#ifndef _BUILD_OTA_E_
		// TODO: step 1: backup UserDB
		UU_PRINTF("BackupDataBase cas9!\n");
		ret = BackupDatabase();
		if (SUCCESS != ret)
		{
			libc_printf("BackupDatabase failed\n");
			return FALSE;
		}
		// TODO: step 2: burn OTA to UserDB

		UU_PRINTF("Burn USB LOADER!\n");
		chunk_id = USER_DB_ID;
		chunk_addr = (UINT32)sto_chunk_goto(&chunk_id, 0xFFFFFFFF, 1); /* We use user_db_start_sector address */
		
		chunk_size = usb_loader_code_size; //+ C_SECTOR_SIZE;
		usb_loader_bin_sectors = chunk_size/C_SECTOR_SIZE;
		
		if(chunk_size%C_SECTOR_SIZE)
			usb_loader_bin_sectors++;
		
		if ((UINT32)ERR_FAILUE == chunk_addr)
		{
			UU_PRINTF("Cannot find userdb's chunk!\n");
			return FALSE;
		}

		flash_pos = chunk_addr / C_SECTOR_SIZE;
		libc_printf("\nusb_loader_code_addr = %x, flash_pos = %x ,sectors = %x\n",usb_loader_code_addr,m_usb_info.user_db_start_sector,usb_loader_bin_sectors);
		ret = BurnBlock((UINT8*)usb_loader_code_addr, m_usb_info.user_db_start_sector, usb_loader_bin_sectors);
		if(SUCCESS != ret)
			return FALSE;
		
#endif

	chunk_id = MAINCODE_ID;
	chunk_addr = (UINT32)sto_chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if ((UINT32)ERR_FAILUE == chunk_addr)
	{
		UU_PRINTF("Cannot find maincode's chunk!\n");
		return FALSE;
	}
	// burn new maincode.bin
	// main code chunk addr and size
	chunk_size = main_code_size;
	if (ver_info.m_m_ver > ver_info.m_f_ver)
	{
		UU_PRINTF("upgrade main code\n");
		flash_pos = chunk_addr / C_SECTOR_SIZE;
		ret = BurnBlock((UINT8 *)main_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
		if (SUCCESS != ret)
			return FALSE;
	}
	// see code chunk addr and size
	chunk_addr += chunk_size;
	chunk_size = see_code_size;
	if (ver_info.s_m_ver > ver_info.s_f_ver)
	{
		UU_PRINTF("upgrade see code\n");
		flash_pos = chunk_addr / C_SECTOR_SIZE;
		ret = BurnBlock((UINT8 *)see_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
		if (SUCCESS != ret)
			return FALSE;
	}

#ifndef _BUILD_OTA_E_
		// TODO: step 3 burn back UserDB
		UU_PRINTF("BurnBack UserDB!\n");
	//	libc_printf("m_usb_info.backup_db_addr = %x, m_usb_info.user_db_start_sector=%x, m_usb_info.user_db_start_sector = %d\n",
	//				m_usb_info.backup_db_addr,m_usb_info.user_db_start_sector,m_usb_info.user_db_sectors);
		ret = BurnBlock((UINT8*)m_usb_info.backup_db_addr, m_usb_info.user_db_start_sector, m_usb_info.user_db_sectors);
        if(SUCCESS != ret)
            return FALSE;
#endif	
    return TRUE;
}

#else

struct usbupg_ver_info
{
	UINT32 m_f_ver;	// main code in flash version
	UINT32 m_m_ver;	// main code in memory version
	UINT32 s_f_ver;	// see code in flash version
	UINT32 s_m_ver;	// see code in memory version
};
static INT32 InitStorage()
{
    m_StoDevice = (struct sto_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_STO);
    if(NULL == m_StoDevice)
    {
        UU_PRINTF("%s: can not get sto device\n", __FUNCTION__);
        return ERR_NO_DEV;
    }

    INT32 er = sto_open(m_StoDevice);
    if(SUCCESS != er)
    {
        UU_PRINTF("%s: can not open sto device\n", __FUNCTION__);
    }

	
    return er;
}
static BOOL usbupg_check(struct usbupg_ver_info *ver_info,UINT8 *pbuff, UINT32 buf_len)
{
	struct sto_device *flash_dev = NULL;
	UINT8 *cipher_addr;
	UINT32 cipher_len;
	UINT8 *addr;	
	UINT32 len;
	UINT32 chunk_id = 0;
	UINT8 *data= NULL;
	UINT32 data_len = 0;
	UINT8 key_pos;
	int ret;
	CHUNK_HEADER chunk_header;	
	
	if (NULL == pbuff || 0 == buf_len)
	{
		return FALSE;
	}
	//init chunk
	chunk_init(pbuff, buf_len);
	// decrypt universal key, fetch public key from flash
	if (decrypt_universal_key(&key_pos, DECRPT_KEY_ID) < 0)
	{
		UU_PRINTF("Decrypt universal key failed!\n");
		return FALSE;
	}
	
	// get the versions of codes in flash 
	cipher_addr = pbuff + buf_len;
	cipher_len = 0x200000;
	flash_cipher_buf_init(cipher_addr, cipher_len);
	
	addr = cipher_addr + cipher_len;

	UU_PRINTF("check main code in flash\n");
	len = 0;
	ret = aes_cbc_decrypt_chunk(key_pos, MAIN_CODE_CHUNK_ID, addr, &len);
	if ((ret == 0) && (len != 0))
		ver_info->m_f_ver = get_code_version(addr, len);

	UU_PRINTF("check see code in flash\n");
	len = 0;
	ret = aes_cbc_decrypt_chunk(key_pos, SEE_CODE_CHUNK_ID, addr, &len);
	if ((ret == 0) && (len != 0))
		ver_info->s_f_ver = get_code_version(addr, len);

	UU_PRINTF("check main code in memory\n");
	chunk_id = MAIN_CODE_CHUNK_ID;
	main_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (main_code_addr)
	{
		data = (UINT8 *)main_code_addr;
		main_code_size = fetch_long(data + CHUNK_OFFSET);
		data_len = fetch_long(data + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
		data += CHUNK_HEADER_SIZE;
		if (aes_cbc_decrypt_ram_chunk(key_pos, addr, data, data_len) == 0)
			ver_info->m_m_ver = get_code_version(addr, data_len);
	}

	UU_PRINTF("check see code in memory\n");
	chunk_id = SEE_CODE_CHUNK_ID;
	see_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (see_code_addr)
	{
		data = (UINT8 *)see_code_addr;
		see_code_size = fetch_long(data + CHUNK_OFFSET);
		data_len = fetch_long(data + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
		data += CHUNK_HEADER_SIZE;
		if (aes_cbc_decrypt_ram_chunk(key_pos, addr, data, data_len) == 0)
			ver_info->s_m_ver = get_code_version(addr, data_len);
	}

	UU_PRINTF("version info:  (0x%X, 0x%X), (0x%X, 0x%X)\n",
		ver_info->m_f_ver,ver_info->m_m_ver, ver_info->s_f_ver, ver_info->s_m_ver);

	ce_ioctl((pCE_DEVICE)dev_get_by_id(HLD_DEV_TYPE_CE, 0), IO_CRYPT_POS_SET_IDLE, key_pos);

	return TRUE;
}

static INT32 BurnBlock(UINT8 *pBuffer, UINT32 Pos, UINT8 NumSectors)
{
	struct sto_device *sto_dev = m_StoDevice;
    UINT32 param[2];
    INT32 offset, er = SUCCESS;
    UINT8 i;

    for(i=0; i<NumSectors; i++)
    {
        offset = (Pos + i) * C_SECTOR_SIZE;
        param[0] = (UINT32)offset;
        param[1] = C_SECTOR_SIZE >> 10; // length in K bytes
        UU_PRINTF("%s: erase sector %d\n", __FUNCTION__, Pos+i);
        er = sto_io_control(sto_dev, STO_DRIVER_SECTOR_ERASE_EXT, param);
        if(er != SUCCESS)
        {
            UU_PRINTF("%s: erase sector %d failed\n", __FUNCTION__, i);
            break;
        }

        if(pBuffer)
        {
            UU_PRINTF("%s: seek sector %d, offset = %xh\n", __FUNCTION__, Pos+i,offset);
            if(sto_lseek(sto_dev, offset, STO_LSEEK_SET) != offset)
            {
                UU_PRINTF("%s: seek sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }

            UU_PRINTF("%s: write sector %d, src = %xh\n", __FUNCTION__, Pos+i,&pBuffer[C_SECTOR_SIZE * i]);
            if(sto_write(sto_dev, &pBuffer[C_SECTOR_SIZE * i], C_SECTOR_SIZE) != C_SECTOR_SIZE)
            {
                UU_PRINTF("%s: write sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }
        }
	  upg_secotrs_index ++;
 	  win_usbupg_process_update(upg_secotrs_index*100/upg_total_sectors);       
    }
    return er;
}
static BOOL win_usb_burnflash(struct usbupg_ver_info ver_info)
{
	BOOL fw_not_match = FALSE;
    	win_popup_choice_t choice;
    	UINT8 back_saved;
	struct sto_device *flash_dev = NULL;
	UINT32 chunk_id, chunk_addr, chunk_size;

	UINT32 upgrade_size = 0;
	if (ver_info.m_m_ver > ver_info.m_f_ver)
		upgrade_size += main_code_size;
	
	if (ver_info.s_m_ver > ver_info.s_f_ver)
		upgrade_size += see_code_size;
	
	if (upgrade_size == 0)
	{
		win_compopup_init(WIN_POPUP_TYPE_OK);
		win_compopup_set_msg("Nothing need to be upgrade!", NULL, 0);
		win_compopup_set_default_choice(WIN_POP_CHOICE_YES);
		win_compopup_open_ext(&back_saved);
		return FALSE;
	}

	upg_total_sectors = upgrade_size / C_SECTOR_SIZE;
	upg_secotrs_index = 0;	
	InitStorage();
	
	UINT32 flash_pos;
	UINT32 ret;
	chunk_id = MAINCODE_ID;
	chunk_addr = (UINT32)sto_chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if ((UINT32)ERR_FAILUE == chunk_addr)
	{
		UU_PRINTF("Cannot find maincode's chunk!\n");
		return FALSE;
	}
	// burn new maincode.bin
	// main code chunk addr and size
	chunk_size = main_code_size;
	if (ver_info.m_m_ver > ver_info.m_f_ver)
	{
		UU_PRINTF("upgrade main code\n");
		flash_pos = chunk_addr / C_SECTOR_SIZE;
		ret = BurnBlock((UINT8 *)main_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
		if (SUCCESS != ret)
			return FALSE;
	}
	// see code chunk addr and size
	chunk_addr += chunk_size;
	chunk_size = see_code_size;
	if (ver_info.s_m_ver > ver_info.s_f_ver)
	{
		UU_PRINTF("upgrade see code\n");
		flash_pos = chunk_addr / C_SECTOR_SIZE;
		ret = BurnBlock((UINT8 *)see_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
		if (SUCCESS != ret)
			return FALSE;
	}
    return TRUE;
}
#endif
#endif

#ifdef _VMX_CA_STD_ENABLE_
#define C_SECTOR_SIZE       0x10000
#define READ_USBUPG_BUFFER_SIZE 0x600000

static UINT32 upg_total_sectors;
static UINT32 upg_secotrs_index;
static UINT32 main_code_addr;
static UINT32 main_code_size;
static UINT32 see_code_addr;
static UINT32 see_code_size;
#ifdef BACKUP_USB_LOADER
static UINT32 usb_loader_code_addr;
static UINT32 usb_loader_code_size;
static UINT32 usb_loader_bin_size,usb_loader_bin_sectors;
static UINT32 backup_db_addr, backup_db_size;
static UINT32 user_db_start_sector, user_db_sectors, user_db_addr_offset,user_db_len;
static UINT32 usb_tmp_buf_addr,usb_tmp_buf_size;
#endif
static struct sto_device *m_StoDevice = NULL;
struct usbupg_ver_info
{
	UINT32 m_f_ver;	// main code in flash version
	UINT32 m_m_ver;	// main code in memory version
	UINT32 s_f_ver;	// see code in flash version
	UINT32 s_m_ver;	// see code in memory version
#ifdef BACKUP_USB_LOADER
	UINT32 u_m_ver;	//usb loader in memory version
#endif

};
static INT8 Char2Hex(UINT8 ch)
{
	INT8 ret =  - 1;
	if ((ch <= 0x39) && (ch >= 0x30))
	// '0'~'9'
		ret = ch &0xf;
	else if ((ch <= 102) && (ch >= 97))
	//'a'~'f'
		ret = ch - 97+10;
	else if ((ch <= 70) && (ch >= 65))
	//'A'~'F'
		ret = ch - 65+10;

	return ret;
}
static UINT32 Str2UINT32(UINT8 *str, UINT8 len)
{
	UINT32 ret = 0;
	UINT8 i;
	INT temp;

	if (str == NULL)
		return 0;

	for (i = 0; i < len; i++)
	{
		temp = Char2Hex(*str++);
		if (temp ==  - 1)
			return 0;

		ret = (ret << 4) | temp;
	}

	return ret;
}
static INT32 InitStorage()
{
    m_StoDevice = (struct sto_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_STO);
    if(NULL == m_StoDevice)
    {
        UU_PRINTF("%s: can not get sto device\n", __FUNCTION__);
        return ERR_NO_DEV;
    }
    INT32 er = sto_open(m_StoDevice);
    if(SUCCESS != er)
    {
        UU_PRINTF("%s: can not open sto device\n", __FUNCTION__);
    }	
    return er;
}

static INT32 BackupDatabase()
{
	struct sto_device *sto_dev = m_StoDevice;
    INT32 er;

	if(sto_lseek(sto_dev, (INT32)user_db_addr_offset, STO_LSEEK_SET) !=  (INT32)user_db_addr_offset)
        return ERR_FAILED;
	if(sto_read(sto_dev, (UINT8 *)backup_db_addr, (INT32)user_db_len) != (INT32)user_db_len)
        return ERR_FAILED;
    return SUCCESS;
}

static BOOL UsbUpg_set_memory(UINT8 *pBuff,UINT32 length)
{
	UINT32 addr_offset, len;
	
	if(length>READ_USBUPG_BUFFER_SIZE)
	{
		UU_PRINTF("buffer overlaping\n");
		return FALSE;
	}
	usb_tmp_buf_addr=pBuff+READ_USBUPG_BUFFER_SIZE;
	usb_tmp_buf_size=0x200000;
	backup_db_addr=usb_tmp_buf_addr+usb_tmp_buf_size;
	backup_db_size = 0x200000;

	// init user_db addrss
	if(!api_get_chunk_add_len(USER_DB_ID, &addr_offset, &len))
	{
		UU_PRINTF("Cannot find user db chunk\n");
		return FALSE;
	}
	user_db_addr_offset = addr_offset;
	user_db_len=len;
	user_db_start_sector = user_db_addr_offset/C_SECTOR_SIZE;
	user_db_sectors = user_db_len/C_SECTOR_SIZE;
	if(user_db_len%C_SECTOR_SIZE)
	{
		user_db_sectors++;
	}		
	return TRUE;
}
extern int verifySignature_std( UINT8* src, UINT8* dest, CHUNK_HEADER hdr,UINT8 *errorCode);
static BOOL usbupg_check(struct usbupg_ver_info *ver_info,UINT8 *pbuff, UINT32 buf_len)
{
	UINT32 chunk_id = 0;
	UINT8 *data;
	UINT8 *block_addr;
	int ret;	
	UINT8* tmp_buffer;
	UINT32 len;
	UINT8 errorCode;
	CHUNK_HEADER chunk_header;	
	UINT8 verify_result=0;

	#define SAVE_MAIN			0x1
	#define SAVE_SEE			0x2
	#define SAVE_USB_LOADER		0x4
	
	if (NULL == pbuff || 0 == buf_len)
	{
		return FALSE;
	}
	//init chunk
	chunk_init(pbuff, buf_len);	
	tmp_buffer = usb_tmp_buf_addr;
	MG_Setup_CRC_Table();	
#ifdef BACKUP_USB_LOADER
	UU_PRINTF("check usb loader in memory\n");
	if(!get_chunk_add_len(USER_DB_ID, &usb_loader_code_addr, &len)) // Got usb_loader_code_addr : add chunk header already
	{
		UU_PRINTF("cannot find user db in memory\n");
		return FALSE;
	}	
	usb_loader_code_addr=usb_loader_code_addr+len; //since ota loader data is appended to the fw data
	if (usb_loader_code_addr)
	{		
		chunk_id = OTA_LOADER_ID;
		block_addr = (UINT8 *)usb_loader_code_addr;	
		if(!get_chunk_header(chunk_id, &chunk_header))
		{
			UU_PRINTF("cannot find ota loader in memory\n");
			//ret = FALSE;
			//return ret;
			#if 1
			chunk_header.id= fetch_long(block_addr + CHUNK_ID);
			chunk_header.len= fetch_long(block_addr + CHUNK_LENGTH);
			chunk_header.offset=fetch_long(block_addr + CHUNK_OFFSET);		
			chunk_header.crc=fetch_long(block_addr + CHUNK_CRC);		
			#endif
		}	
		
		usb_loader_code_size = chunk_header.offset;
		usb_loader_bin_size=usb_loader_code_size+C_SECTOR_SIZE; //add a sector for cfg, backup loader and cfg (match ota structure in bootloader)
		usb_loader_bin_sectors=usb_loader_bin_size/C_SECTOR_SIZE;
		if(usb_loader_bin_size%C_SECTOR_SIZE)
		{
			usb_loader_bin_sectors++;
		}
		UU_PRINTF("usb_loader_bin_size=%d, usb_loader_bin_sectors=%d\n",usb_loader_bin_size, usb_loader_bin_sectors);
		UU_PRINTF("usb_loader_code_addr=0x%x, usb_loader_code_size=0x%x\n",usb_loader_code_addr, usb_loader_code_size);
		UU_PRINTF("usb_loader_id=0x%x 0x%x\n",*((UINT8 *)usb_loader_code_addr),*((UINT8 *)usb_loader_code_addr+1));
		data = block_addr;
		ret=verifySignature_std(data, tmp_buffer, chunk_header,&errorCode);
		if(ret==1)	//app can be started
		{
			UU_PRINTF("usb loader cannot be started in loader mode\n");
		}
		else	// don't start app
		{
			if(errorCode==2)	//store app to flash and reboot later
			{
				ver_info->u_m_ver = Str2UINT32(chunk_header.version,8);				
				UU_PRINTF("usb loader verify ok and re-encrypt\n");
				verify_result|=SAVE_USB_LOADER;
			}
			else if(errorCode==1)
			{
				UU_PRINTF("usb code verify failed\n");
			}
		}
	}
	UU_PRINTF("usb loader: 0x%X, 0x%X\n", usb_loader_code_addr, usb_loader_code_size);
#endif

	UU_PRINTF("check main code in memory\n");
	chunk_id = MAINCODE_ID;
	main_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (main_code_addr)
	{		
		if(!get_chunk_header(chunk_id, &chunk_header))
		{
			UU_PRINTF("cannot find main code in memory\n");
			ret = FALSE;
			return ret;
		}	
		block_addr = (UINT8 *)main_code_addr;
		main_code_size = chunk_header.offset;
		data = block_addr;
		ret=verifySignature_std(data, tmp_buffer, chunk_header,&errorCode);		
		if(ret==1)	//app can be started
		{
			UU_PRINTF("main code cannot be started in loader mode\n");
		}
		else	// don't start app
		{
			if(errorCode==2)	//store app to flash and reboot later
			{
				ver_info->m_m_ver = Str2UINT32(chunk_header.version,8);				
				UU_PRINTF("main code verify ok and re-encrypt\n");
				verify_result|=SAVE_MAIN;
			}
			else if(errorCode==1)
			{
				UU_PRINTF("main code verify failed\n");
			}
		}
	}
	UU_PRINTF("main code: 0x%X, 0x%X\n", main_code_addr, main_code_size);

	UU_PRINTF("check see code in memory\n");
	chunk_id = SEECODE_ID;
	see_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (see_code_addr)
	{
		if(!get_chunk_header(chunk_id, &chunk_header))
		{
			UU_PRINTF("cannot find see code in memory\n");
			ret = FALSE;
			return ret;
		}
		block_addr = (UINT8 *)see_code_addr;
		see_code_size = chunk_header.offset;
		data = block_addr;
		ret=verifySignature_std(data, tmp_buffer, chunk_header,&errorCode);
		if(ret==1)	//app can be started
		{
			UU_PRINTF("see code cannot be started in loader mode\n");
		}
		else	// don't start app
		{
			if(errorCode==2)	//store app to flash and reboot later
			{
				ver_info->s_m_ver = Str2UINT32(chunk_header.version,8);
				UU_PRINTF("see code verify ok and re-encrypt\n");
				verify_result|=SAVE_SEE;
			}
			else if(errorCode==1)
			{
				UU_PRINTF("see code verify failed\n");
			}
		}
		
	}
	UU_PRINTF("see code: 0x%X, 0x%X\n", see_code_addr, see_code_size);

	chunk_id=MAINCODE_ID;
	if(sto_get_chunk_header(chunk_id, &chunk_header))
	{
		ver_info->m_f_ver = Str2UINT32(chunk_header.version, 8);
	}

	chunk_id=SEECODE_ID;
	if(sto_get_chunk_header(chunk_id, &chunk_header))
	{
		ver_info->s_f_ver = Str2UINT32(chunk_header.version, 8);
	}
	
	UU_PRINTF("version info: (0x%X, 0x%X), (0x%X, 0x%X)\n",
		ver_info->m_f_ver,ver_info->m_m_ver, ver_info->s_f_ver, ver_info->s_m_ver);

	UU_PRINTF("verify result=0x%x\n",verify_result);
	if(verify_result==(SAVE_MAIN|SAVE_SEE|SAVE_USB_LOADER))
	{
		return TRUE;	//save apps to flash
	}
	else
	{
		return FALSE;
	}
}
static INT32 BurnBlock(UINT8 *pBuffer, UINT32 Pos, UINT8 NumSectors)
{
	struct sto_device *sto_dev = m_StoDevice;
    UINT32 param[2];
    INT32 offset, er = SUCCESS;
    UINT8 i;

    for(i=0; i<NumSectors; i++)
    {
        offset = (Pos + i) * C_SECTOR_SIZE;
        param[0] = (UINT32)offset;
        param[1] = C_SECTOR_SIZE >> 10; // length in K bytes
        UU_PRINTF("%s: erase sector %d\n", __FUNCTION__, Pos+i);
        er = sto_io_control(sto_dev, STO_DRIVER_SECTOR_ERASE_EXT, param);
        if(er != SUCCESS)
        {
            UU_PRINTF("%s: erase sector %d failed\n", __FUNCTION__, i);
            break;
        }

        if(pBuffer)
        {
            UU_PRINTF("%s: seek sector %d, offset = %xh\n", __FUNCTION__, Pos+i,offset);
            if(sto_lseek(sto_dev, offset, STO_LSEEK_SET) != offset)
            {
                UU_PRINTF("%s: seek sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }

            UU_PRINTF("%s: write sector %d, src = %xh\n", __FUNCTION__, Pos+i,&pBuffer[C_SECTOR_SIZE * i]);
            if(sto_write(sto_dev, &pBuffer[C_SECTOR_SIZE * i], C_SECTOR_SIZE) != C_SECTOR_SIZE)
            {
                UU_PRINTF("%s: write sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }
        }
	  upg_secotrs_index ++;
 	  win_usbupg_process_update(upg_secotrs_index*100/upg_total_sectors);       
    }
    return er;
}

static BOOL win_usb_burnflash(struct usbupg_ver_info ver_info)
{
	BOOL fw_not_match = FALSE;
    	win_popup_choice_t choice;
    	UINT8 back_saved;
	struct sto_device *flash_dev = NULL;
	UINT32 chunk_id, chunk_addr, chunk_size;
	
	UINT8 bskip=FALSE;
	#define SKIP_VER_CHECK
	#ifdef SKIP_VER_CHECK
		bskip=TRUE;	
	#endif

	UINT32 upgrade_size = 0;	
	if ((bskip) || (ver_info.m_m_ver > ver_info.m_f_ver))
		upgrade_size += main_code_size;
	
	if ((bskip)||(ver_info.s_m_ver > ver_info.s_f_ver))
		upgrade_size += see_code_size;
	
	if (upgrade_size == 0)
	{
		win_compopup_init(WIN_POPUP_TYPE_OK);
		win_compopup_set_msg("Nothing need to be upgrade!", NULL, 0);
		win_compopup_set_default_choice(WIN_POP_CHOICE_YES);
		win_compopup_open_ext(&back_saved);
		return FALSE;
	}
	
#ifndef _BUILD_USB_LOADER_
#ifdef BACKUP_USB_LOADER
	upgrade_size += usb_loader_bin_size;
	upgrade_size += user_db_len;
#endif
#else
	upgrade_size += user_db_len;
#endif

	upg_total_sectors = upgrade_size / C_SECTOR_SIZE;
	upg_secotrs_index = 0;	
	InitStorage();
	
	UINT32 flash_pos;
	UINT32 ret;

#ifdef BACKUP_USB_LOADER
#ifndef _BUILD_USB_LOADER_
	UU_PRINTF("BackupDataBase!\n");
	ret = BackupDatabase();
	if (SUCCESS != ret)
		return FALSE;
	
	UU_PRINTF("Burn USBLOADER!\n");
	UU_PRINTF("burn usb_loader_id=0x%x 0x%x\n",*((UINT8 *)usb_loader_code_addr),*((UINT8 *)usb_loader_code_addr+1));
	ret = BurnBlock((UINT8 *)usb_loader_code_addr, user_db_start_sector, usb_loader_bin_sectors);
    if(SUCCESS != ret)
    	return FALSE;
#endif
#endif

	chunk_id = MAINCODE_ID;
	chunk_addr = (UINT32)sto_chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if ((UINT32)ERR_FAILUE == chunk_addr)
	{
		UU_PRINTF("Cannot find maincode's chunk!\n");
		return FALSE;
	}
	// burn new maincode.bin
	// main code chunk addr and size
	chunk_size = main_code_size;
	
	if ((bskip) ||(ver_info.m_m_ver > ver_info.m_f_ver))
	{
		UU_PRINTF("upgrade main code\n");
		flash_pos = chunk_addr / C_SECTOR_SIZE;
		ret = BurnBlock((UINT8 *)main_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
		if (SUCCESS != ret)
			return FALSE;
	}
	// see code chunk addr and size
	chunk_addr += chunk_size;
	chunk_size = see_code_size;
	#if 1
	#else	//Test case of try usb loader
			UU_PRINTF("TEST CASE: Force wrong value of See chunk!\n");
			*(UINT32*)((UINT8*)see_code_addr+CHUNK_CRC)=0; 
	#endif
	if ((bskip)||(ver_info.s_m_ver > ver_info.s_f_ver))
	{
		UU_PRINTF("upgrade see code\n");
		flash_pos = chunk_addr / C_SECTOR_SIZE;
		ret = BurnBlock((UINT8 *)see_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
		if (SUCCESS != ret)
			return FALSE;

	#ifdef BACKUP_USB_LOADER
	#ifndef _BUILD_USB_LOADER_
		// TODO: burn back UserDB
		#if 1
		UU_PRINTF("BurnBack UserDB!\n");
		ret = BurnBlock((UINT8*)backup_db_addr, user_db_start_sector, user_db_sectors);
	    if(SUCCESS != ret)
    	    return FALSE;
		#else //Test case of try usb loader
			UU_PRINTF("TEST CASE: SKIP BurnBack UserDB!\n");
		#endif
	#else
		UU_PRINTF("Reset UserDB!\n");
		ret = BurnBlock((UINT8*)NULL, user_db_start_sector, user_db_sectors);
    	if(SUCCESS != ret)
        	return FALSE;
	#endif
	#endif			
	}
    return TRUE;
}
#endif
#ifdef _VMX_CA_ENABLE_
#define MAIN_CODE_CHUNK_ID		0x01FE0101
#define SEE_CODE_CHUNK_ID		0x06F90101
#define	DECRPT_KEY_ID			0x22DD0100
#define DECRPT_KEY_MASK 		0xFFFF0000
#define C_SECTOR_SIZE       0x10000
static UINT32 upg_total_sectors;
static UINT32 upg_secotrs_index;
static UINT32 main_code_addr;
static UINT32 main_code_size;
static UINT32 see_code_addr;
static UINT32 see_code_size;
#ifdef BACKUP_USB_LOADER
static UINT32 usb_loader_code_addr;
static UINT32 usb_loader_code_size;
static UINT32 usb_loader_bin_size,usb_loader_bin_sectors;
static UINT32 backup_db_addr, backup_db_size;
static UINT32 user_db_start_sector, user_db_sectors, user_db_addr_offset,user_db_len;
static UINT32 usb_tmp_buf_addr,usb_tmp_buf_size;
#endif
static struct sto_device *m_StoDevice = NULL;
struct usbupg_ver_info
{
	UINT32 m_f_ver;	// main code in flash version
	UINT32 m_m_ver;	// main code in memory version
	UINT32 s_f_ver;	// see code in flash version
	UINT32 s_m_ver;	// see code in memory version
#ifdef BACKUP_USB_LOADER
	UINT32 u_m_ver;	//usb loader in memory version
#endif
};
#define READ_USBUPG_BUFFER_SIZE 0x520000
static INT8 Char2Hex(UINT8 ch)
{
	INT8 ret =  - 1;
	if ((ch <= 0x39) && (ch >= 0x30))
	// '0'~'9'
		ret = ch &0xf;
	else if ((ch <= 102) && (ch >= 97))
	//'a'~'f'
		ret = ch - 97+10;
	else if ((ch <= 70) && (ch >= 65))
	//'A'~'F'
		ret = ch - 65+10;

	return ret;
}

static UINT32 Str2UINT32(UINT8 *str, UINT8 len)
{
	UINT32 ret = 0;
	UINT8 i;
	INT temp;

	if (str == NULL)
		return 0;

	for (i = 0; i < len; i++)
	{
		temp = Char2Hex(*str++);
		if (temp ==  - 1)
			return 0;

		ret = (ret << 4) | temp;
	}

	return ret;
}

static INT32 InitStorage()
{
    m_StoDevice = (struct sto_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_STO);
    if(NULL == m_StoDevice)
    {
        UU_PRINTF("%s: can not get sto device\n", __FUNCTION__);
        return ERR_NO_DEV;
    }

    INT32 er = sto_open(m_StoDevice);
    if(SUCCESS != er)
    {
        UU_PRINTF("%s: can not open sto device\n", __FUNCTION__);
    }

	
    return er;
}

static INT32 BackupDatabase()
{
	struct sto_device *sto_dev = m_StoDevice;
    INT32 er;

	if(sto_lseek(sto_dev, (INT32)user_db_addr_offset, STO_LSEEK_SET) !=  (INT32)user_db_addr_offset)
        return ERR_FAILED;
	if(sto_read(sto_dev, (UINT8 *)backup_db_addr, (INT32)user_db_len) != (INT32)user_db_len)
        return ERR_FAILED;
    return SUCCESS;
}

static BOOL UsbUpg_set_memory(UINT8 *pBuff,UINT32 length)
{
	UINT32 addr_offset, len;
	
	if(length>READ_USBUPG_BUFFER_SIZE)
	{
		UU_PRINTF("buffer overlaping\n");
		return FALSE;
	}
	usb_tmp_buf_addr=pBuff+READ_USBUPG_BUFFER_SIZE;
	usb_tmp_buf_size=0x200000;
	backup_db_addr=usb_tmp_buf_addr+usb_tmp_buf_size;
	backup_db_size = 0x200000;

	// init user_db addrss
	if(!api_get_chunk_add_len(0x04FB0100, &addr_offset, &len))
	{
		UU_PRINTF("Cannot find user db chunk\n");
		return FALSE;
	}

	user_db_addr_offset = addr_offset;
	user_db_len=len;
	user_db_start_sector = user_db_addr_offset/C_SECTOR_SIZE;
	user_db_sectors = user_db_len/C_SECTOR_SIZE;
	if(user_db_len%C_SECTOR_SIZE)
	{
		user_db_sectors++;
	}
		
	return TRUE;
}

static BOOL usbupg_check(struct usbupg_ver_info *ver_info,UINT8 *pbuff, UINT32 buf_len)
{
	//struct sto_device *flash_dev = NULL;
	UINT32 chunk_id = 0;
	UINT8 *data;
	UINT32 data_len;
	UINT8 *block_addr;
	int ret;	
	uint8_t* signature;
	uint8_t* tmp_buffer;
	uint32_t len, maxLen;
	uint8_t mode, errorCode;
	unsigned int header_crc=0;
	//UINT32 block_header, version;
	CHUNK_HEADER blk_header;
	UINT8 verify_result=0;

	#define SIGNATURE_SIZE 		256
	#define SAVE_MAIN			0x1
	#define SAVE_SEE			0x2
	#define SAVE_USB_LOADER		0x4
	
	if (NULL == pbuff || 0 == buf_len)
	{
		return FALSE;
	}
	//init chunk
	chunk_init(pbuff, buf_len);
	
	tmp_buffer = usb_tmp_buf_addr;
	MG_Setup_CRC_Table();
	
#ifdef BACKUP_USB_LOADER
	UU_PRINTF("check usb loader in memory\n");

	if(!get_chunk_add_len(0x04FB0100, &usb_loader_code_addr, &len))
	{
		UU_PRINTF("cannot find user db in memory\n");
		return FALSE;
	}
	
	usb_loader_code_addr=usb_loader_code_addr+len;
	if (usb_loader_code_addr)
	{
		
		block_addr = (UINT8 *)usb_loader_code_addr;
		usb_loader_code_size = fetch_long(block_addr + CHUNK_OFFSET);
		usb_loader_bin_size=usb_loader_code_size+C_SECTOR_SIZE; //add a sector for cfg, backup loader and cfg (match ota structure in bootloader)
		usb_loader_bin_sectors=usb_loader_bin_size/C_SECTOR_SIZE;
		if(usb_loader_bin_size%C_SECTOR_SIZE)
		{
			usb_loader_bin_sectors++;
		}
		UU_PRINTF("usb_loader_bin_size=%d, usb_loader_bin_sectors=%d\n",usb_loader_bin_size, usb_loader_bin_sectors);
		UU_PRINTF("usb_loader_code_addr=0x%x, usb_loader_code_size=0x%x\n",usb_loader_code_addr, usb_loader_code_size);
		UU_PRINTF("usb_loader_id=0x%x 0x%x\n",*((UINT8 *)usb_loader_code_addr),*((UINT8 *)usb_loader_code_addr+1));
		data_len = fetch_long(block_addr + CHUNK_LENGTH);
		data = block_addr+CHUNK_HEADER_SIZE;

		len=data_len-(CHUNK_HEADER_SIZE-CHUNK_NAME)-SIGNATURE_SIZE;
		signature=data+len;
		//maxLen=usb_loader_code_size; //Clarify 20120806
		maxLen=len;
		mode=1;		//from loader
		ret=BC_VerifySignature(signature, data, tmp_buffer, len, maxLen, mode,&errorCode);
		if(ret==1)	//app can be started
		{
			UU_PRINTF("usb loader cannot be started in loader mode\n");
		}
		else	// don't start app
		{
			if(errorCode==2)	//store app to flash and reboot later
			{
				ver_info->u_m_ver = Str2UINT32(block_addr+CHUNK_VERSION, 8);
				//calculate crc value for chunk header
				header_crc=MG_Table_Driven_CRC(0xFFFFFFFF, block_addr+CHUNK_NAME, data_len);
				*(block_addr+CHUNK_CRC)=(UINT8)(header_crc>>24);
				*(block_addr+CHUNK_CRC+1)=(UINT8)(header_crc>>16);
				*(block_addr+CHUNK_CRC+2)=(UINT8)(header_crc>>8);
				*(block_addr+CHUNK_CRC+3)=(UINT8)(header_crc);
				UU_PRINTF("ota block header_crc=0x%x first byte=0x%x\n",header_crc,*(block_addr+CHUNK_CRC));
				UU_PRINTF("usb loader verify ok and re-encrypt\n");
				verify_result|=SAVE_USB_LOADER;
			}
			else if(errorCode==1)
			{
				UU_PRINTF("usb code verify failed\n");
			}
		}

	}
	

	UU_PRINTF("usb loader: 0x%X, 0x%X\n", usb_loader_code_addr, usb_loader_code_size);

#endif

	UU_PRINTF("check main code in memory\n");
	chunk_id = MAIN_CODE_CHUNK_ID;
	main_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (main_code_addr)
	{
		block_addr = (UINT8 *)main_code_addr;
		main_code_size = fetch_long(block_addr + CHUNK_OFFSET);
		data_len = fetch_long(block_addr + CHUNK_LENGTH);
		data = block_addr+CHUNK_HEADER_SIZE;

		len=data_len-(CHUNK_HEADER_SIZE-CHUNK_NAME)-SIGNATURE_SIZE;
		signature=data+len;
		//maxLen=main_code_size;  //Clarify 20120806
		maxLen=len;
		mode=1;		//from loader
		ret=BC_VerifySignature(signature, data, tmp_buffer, len, maxLen, mode,&errorCode);
		if(ret==1)	//app can be started
		{
			UU_PRINTF("main code cannot be started in loader mode\n");
		}
		else	// don't start app
		{
			if(errorCode==2)	//store app to flash and reboot later
			{
				ver_info->m_m_ver = Str2UINT32(block_addr+CHUNK_VERSION, 8);
				//calculate crc value for chunk header
				header_crc=MG_Table_Driven_CRC(0xFFFFFFFF, block_addr+CHUNK_NAME, data_len);
				*(block_addr+CHUNK_CRC)=(UINT8)(header_crc>>24);
				*(block_addr+CHUNK_CRC+1)=(UINT8)(header_crc>>16);
				*(block_addr+CHUNK_CRC+2)=(UINT8)(header_crc>>8);
				*(block_addr+CHUNK_CRC+3)=(UINT8)(header_crc);
				UU_PRINTF("main block header_crc=0x%x first byte=0x%x\n",header_crc,*(block_addr+CHUNK_CRC));
				UU_PRINTF("main code verify ok and re-encrypt\n");
				verify_result|=SAVE_MAIN;
			}
			else if(errorCode==1)
			{
				UU_PRINTF("main code verify failed\n");
			}
		}
	}
	UU_PRINTF("main code: 0x%X, 0x%X\n", main_code_addr, main_code_size);

	UU_PRINTF("check see code in memory\n");
	chunk_id = SEE_CODE_CHUNK_ID;
	see_code_addr = (UINT32)chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if (see_code_addr)
	{
		block_addr = (UINT8 *)see_code_addr;
		see_code_size = fetch_long(block_addr + CHUNK_OFFSET);
		data_len = fetch_long(block_addr + CHUNK_LENGTH);
		data = block_addr+CHUNK_HEADER_SIZE;

		len=data_len-(CHUNK_HEADER_SIZE-CHUNK_NAME)-SIGNATURE_SIZE;
		signature=data+len;
		//maxLen=see_code_size;  //Clarify 20120806
		maxLen=len;
		mode=1;		//from loader
		ret=BC_VerifySignature(signature, data, tmp_buffer, len, maxLen, mode,&errorCode);
		if(ret==1)	//app can be started
		{
			UU_PRINTF("see code cannot be started in loader mode\n");
		}
		else	// don't start app
		{
			if(errorCode==2)	//store app to flash and reboot later
			{
				ver_info->s_m_ver = Str2UINT32(block_addr+CHUNK_VERSION, 8);
				//calculate crc value for chunk header
				header_crc=MG_Table_Driven_CRC(0xFFFFFFFF, block_addr+CHUNK_NAME, data_len);
				*(block_addr+CHUNK_CRC)=(UINT8)(header_crc>>24);
				*(block_addr+CHUNK_CRC+1)=(UINT8)(header_crc>>16);
				*(block_addr+CHUNK_CRC+2)=(UINT8)(header_crc>>8);
				*(block_addr+CHUNK_CRC+3)=(UINT8)(header_crc);
				UU_PRINTF("see block header_crc=0x%x first byte=0x%x\n",header_crc,*(block_addr+CHUNK_CRC));
				UU_PRINTF("see code verify ok and re-encrypt\n");
				verify_result|=SAVE_SEE;
			}
			else if(errorCode==1)
			{
				UU_PRINTF("see code verify failed\n");
			}
		}
		
	}
	UU_PRINTF("see code: 0x%X, 0x%X\n", see_code_addr, see_code_size);


	chunk_id=MAIN_CODE_CHUNK_ID;
	if(sto_get_chunk_header(chunk_id, &blk_header))
	{
		ver_info->m_f_ver = Str2UINT32(blk_header.version, 8);
	}

	chunk_id=SEE_CODE_CHUNK_ID;
	if(sto_get_chunk_header(chunk_id, &blk_header))
	{
		ver_info->s_f_ver = Str2UINT32(blk_header.version, 8);
	}
	
	UU_PRINTF("version info: (0x%X, 0x%X), (0x%X, 0x%X)\n",
		ver_info->m_f_ver,ver_info->m_m_ver, ver_info->s_f_ver, ver_info->s_m_ver);

	UU_PRINTF("verify result=0x%x\n",verify_result);
	if(verify_result==(SAVE_MAIN|SAVE_SEE|SAVE_USB_LOADER))
	{
		return TRUE;	//save apps to flash
	}
	else
	{
		return FALSE;
	}
}

static INT32 BurnBlock(UINT8 *pBuffer, UINT32 Pos, UINT8 NumSectors)
{
	struct sto_device *sto_dev = m_StoDevice;
    UINT32 param[2];
    INT32 offset, er = SUCCESS;
    UINT8 i;

    for(i=0; i<NumSectors; i++)
    {
        offset = (Pos + i) * C_SECTOR_SIZE;
        param[0] = (UINT32)offset;
        param[1] = C_SECTOR_SIZE >> 10; // length in K bytes
        UU_PRINTF("%s: erase sector %d\n", __FUNCTION__, Pos+i);
        er = sto_io_control(sto_dev, STO_DRIVER_SECTOR_ERASE_EXT, param);
        if(er != SUCCESS)
        {
            UU_PRINTF("%s: erase sector %d failed\n", __FUNCTION__, i);
            break;
        }

        if(pBuffer)
        {
            UU_PRINTF("%s: seek sector %d, offset = %xh\n", __FUNCTION__, Pos+i,offset);
            if(sto_lseek(sto_dev, offset, STO_LSEEK_SET) != offset)
            {
                UU_PRINTF("%s: seek sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }

            UU_PRINTF("%s: write sector %d, src = %xh\n", __FUNCTION__, Pos+i,&pBuffer[C_SECTOR_SIZE * i]);
            if(sto_write(sto_dev, &pBuffer[C_SECTOR_SIZE * i], C_SECTOR_SIZE) != C_SECTOR_SIZE)
            {
                UU_PRINTF("%s: write sector %d failed\n", __FUNCTION__, i);
                er = ERR_FAILED;
                break;
            }
        }
	  upg_secotrs_index ++;
 	  win_usbupg_process_update(upg_secotrs_index*100/upg_total_sectors);       
    }
    return er;
}
static BOOL win_usb_burnflash(struct usbupg_ver_info ver_info)
{
    win_popup_choice_t choice;
    UINT8 back_saved;
	//struct sto_device *flash_dev = NULL;
	UINT32 chunk_id, chunk_addr, chunk_size;

	UINT32 upgrade_size = 0;
	//can upgrade all version in usb upgrade
	//if((ver_info.m_m_ver >= ver_info.m_f_ver)&&(ver_info.s_m_ver >= ver_info.s_f_ver))
	{
		upgrade_size += main_code_size;
		upgrade_size += see_code_size;
	}
	
	if (upgrade_size == 0)
	{
		win_compopup_init(WIN_POPUP_TYPE_OK);
		win_compopup_set_msg("Nothing need to be upgrade!", NULL, 0);
		win_compopup_set_default_choice(WIN_POP_CHOICE_YES);
		win_compopup_open_ext(&back_saved);
		return FALSE;
	}
#ifndef _BUILD_USB_LOADER_
#ifdef BACKUP_USB_LOADER
	upgrade_size += usb_loader_bin_size;
	upgrade_size += user_db_len;
#endif
#else
	upgrade_size += user_db_len;
#endif

	upg_total_sectors = upgrade_size / C_SECTOR_SIZE;
	upg_secotrs_index = 0;	
	InitStorage();
	
	UINT32 flash_pos;
	UINT32 ret;

#ifdef BACKUP_USB_LOADER
#ifndef _BUILD_USB_LOADER_
	UU_PRINTF("BackupDataBase!\n");
	ret = BackupDatabase();
	if (SUCCESS != ret)
		return FALSE;
	
	UU_PRINTF("Burn USBLOADER!\n");
	UU_PRINTF("burn usb_loader_id=0x%x 0x%x\n",*((UINT8 *)usb_loader_code_addr),*((UINT8 *)usb_loader_code_addr+1));
	ret = BurnBlock((UINT8 *)usb_loader_code_addr, user_db_start_sector, usb_loader_bin_sectors);
    if(SUCCESS != ret)
    	return FALSE;
#endif
#endif
	
	chunk_id = MAINCODE_ID;
	chunk_addr = (UINT32)sto_chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	if ((UINT32)ERR_FAILUE == chunk_addr)
	{
		UU_PRINTF("Cannot find maincode's chunk!\n");
		return FALSE;
	}
	// burn new maincode.bin
	// main code chunk addr and size
	chunk_size = main_code_size;

	UU_PRINTF("upgrade main code\n");
	flash_pos = chunk_addr / C_SECTOR_SIZE;
	ret = BurnBlock((UINT8 *)main_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
	if (SUCCESS != ret)
		return FALSE;

	// see code chunk addr and size
	chunk_addr += chunk_size;
	chunk_size = see_code_size;

	UU_PRINTF("upgrade see code\n");
	flash_pos = chunk_addr / C_SECTOR_SIZE;
	ret = BurnBlock((UINT8 *)see_code_addr, flash_pos, chunk_size/C_SECTOR_SIZE);
	if (SUCCESS != ret)
		return FALSE;
#ifdef BACKUP_USB_LOADER
#ifndef _BUILD_USB_LOADER_
	// TODO: burn back UserDB
	UU_PRINTF("BurnBack UserDB!\n");
	ret = BurnBlock((UINT8*)backup_db_addr, user_db_start_sector, user_db_sectors);
    if(SUCCESS != ret)
        return FALSE;
#else
	UU_PRINTF("reset UserDB!\n");
	ret = BurnBlock((UINT8*)NULL, user_db_start_sector, user_db_sectors);
    if(SUCCESS != ret)
        return FALSE;
#endif
#endif	
    return TRUE;
}
#endif


#ifdef CI_PLUS_SUPPORT
static BOOL usbupg_maincode_check(UINT8 *pbuff, UINT32 length)
{
	BOOL ret = TRUE;
	UINT32 data_addr = 0;
	UINT32 data_len = 0;

	if (NULL == pbuff || 0 == length)
	{
		ASSERT(0);
		return FALSE;
	}

	// Even upgrade app.bin, usb_readfile still add CHUNK_HEADER structure to pbuff 
	// and input length is chunk offset
	// & build a total full chunk, so need to fetch raw data & len
	data_addr = (UINT32)pbuff + CHUNK_HEADER_SIZE;
	data_len = fetch_long(pbuff + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
	if (0 != Test_RSA_Ram(data_addr, data_len))
	{
		ret = FALSE;
		return ret;
	}

	return ret;
}

static BOOL usbupg_seecode_check(UINT8 *pbuff, UINT32 length)
{
	BOOL ret = TRUE;
	UINT32 data_addr = 0;
	UINT32 data_len = 0;

	if (NULL == pbuff || 0 == length)
	{
		ASSERT(0);
		return FALSE;
	}

	data_addr = (UINT32)pbuff+ CHUNK_HEADER_SIZE;
	data_len = fetch_long(pbuff + CHUNK_LENGTH) - CHUNK_HEADER_SIZE + CHUNK_NAME;
	if (0 != Test_RSA_Ram(data_addr, data_len))
	{
		ret = FALSE;
		return ret;
	}

	return ret;
}

static BOOL usbupg_allcode_check(UINT8 *pbuff, UINT32 length)
{
	struct sto_device *flash_dev = NULL;
	UINT32 chunk_offset = 0;
	UINT8 bl_signed[256] = {0xFF};
	UINT32 check_cnt = 0;
	BOOL ret = TRUE; // default TRUE, means check success!
	UINT32 chunk_id = 0;
	UINT8 *data_addr = NULL;
	UINT32 data_len = 0;
	CHUNK_HEADER chunk_header;

	if (NULL == pbuff || 0 == length)
	{
		ASSERT(0);
		return FALSE;
	}

	// step 1: bootloader check
	// Current we do not allow upgrade bootloader!!!
//	chunk_offset = fetch_long(pbuff + CHUNK_OFFSET); // get bootloader offset
//	MEMCPY(bl_signed, pbuff + chunk_offset - 0x100, 0x100); // get signed data from source
//	for (check_cnt = 0; check_cnt < 0x100; check_cnt ++)
//	{
//		if (0xFF == bl_signed[check_cnt] || 0x0 == bl_signed[check_cnt])
//		{
//			ret = FALSE;
//			break;
//		}
//	}
//	if (FALSE == ret)
//		return ret;
	
	chunk_init(pbuff, length);	
	// step 2: maincode check
	// get maincode raw data address & length	
	chunk_id = MAINCODE_ID;
	if(!get_chunk_header(chunk_id, &chunk_header))
	{
		ret = FALSE;
		return ret;
	}
	data_addr = chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	data_len = chunk_header.len;
	if (FALSE == usbupg_maincode_check((UINT32)data_addr, data_len)) // this function operate RAW Data and RAW length
	{
		ret = FALSE;
		return ret;
	}

	// step 3: seecode check
	// get raw data address & length from memory
	chunk_id = SEECODE_ID;
	if (!get_chunk_header(chunk_id, &chunk_header))
	{
		ret = FALSE;
		return ret;
	}
	data_addr = chunk_goto(&chunk_id, 0xFFFFFFFF, 1);
	data_len = chunk_header.len;
	if (FALSE == usbupg_seecode_check((UINT32)data_addr, data_len))
	{
		ret = FALSE;
		return ret;
	}

	return ret;
}
#endif

static PRESULT usbupg_item_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
	UINT8 bID,back_saved;
	UINT16 block_idx,file_idx,popup_strid;
	INT32 vscr_idx,length,fileread_ret;
        UINT32 lzo_len1;
        UINT32 lzo_len2;
	char str_buff[20];
	void *pBuff;
	BOOL burnflash_ret;
	VACTION unact;
	PRESULT ret;
	PMULTISEL pMsel;
	lpVSCR apVscr;
	win_popup_choice_t choice;
	USBUPG_BLOCK_TYPE usbupg_type;
	
	ret = PROC_PASS;	
	bID = OSD_GetObjID(pObj);
	switch(event)
	{
		case EVN_UNKNOWN_ACTION:
			unact = (VACTION)(param1>>16);
			if(unact == VACT_ENTER && bID == START_ID)
			{
				win_usbupg_msg_clear();
				win_usbupg_process_update(0);
				vscr_idx = osal_task_get_current_id();
				apVscr = OSD_GetTaskVscr(vscr_idx);
				
				if(usbupg_files_cnt == 0)//no file selected to upgrade
				{
					popup_strid = RS_USBUPG_NO_MATCH_FILE;
				}
				else
				{
					popup_strid = RS_USBUPG_ALERT_NOPLUG;
				}
				//win_usbupg_msg_update(popup_strid);
				win_compopup_init(WIN_POPUP_TYPE_SMSG);
				win_compopup_set_msg(NULL,NULL, popup_strid);
				win_compopup_open_ext(&back_saved);
				osal_task_sleep(2000);
				win_compopup_smsg_restoreback();
				
				if(usbupg_files_cnt == 0)
					return PROC_PASS;//ignore press msg when no file

				OSD_SetAttr(&usbupg_item_con1, C_ATTR_INACTIVE);
				OSD_SetAttr(&usbupg_item_con2, C_ATTR_INACTIVE);
				OSD_SetAttr(&usbupg_item_con3, C_ATTR_INACTIVE);
				OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con1, C_UPDATE_ALL);
				OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con2, C_UPDATE_ALL);
				OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con3, C_UPDATE_ALL);

				pMsel = &usbupg_sel_upgrade_type;
				switch(OSD_GetMultiselSel(pMsel))
				{
					case 0:
						block_idx = 0;
						break;
					default:
						block_idx = OSD_GetMultiselSel(pMsel)+ 1;
				}
				
				pMsel = &usbupg_filelist_sel;
				file_idx = OSD_GetMultiselSel(pMsel);

				usbupg_type = usbupg_get_block_type(block_idx);
				if(USBUPG_ALLCODE == usbupg_type || USBUPG_BOOTLOADER == usbupg_type)
				{
#ifndef CI_PLUS_SUPPORT
					// if we do AllCode/BootLoader Upgrade, we need to upgrade bootloader chunk
					set_upgrade_bloader_flag(1);
#else
					// Oncer: for CI+, do not allow to upgrade bootloader
					set_upgrade_bloader_flag(0);
#endif
				}
				else
				{
					set_upgrade_bloader_flag(0);
				}
#if (defined(_CAS9_CA_ENABLE_) || defined(_VMX_CA_STD_ENABLE_) || defined(_VMX_CA_ENABLE_))
				set_upgrade_bloader_flag(0);
#endif
				usbupg_get_blockinfo(block_idx,str_buff,&length);//get chunk length
#if (defined(_CAS9_CA_ENABLE_) || defined(_VMX_CA_STD_ENABLE_) || defined(_VMX_CA_ENABLE_))
				pBuff = (void *)(__MM_PVR_VOB_BUFFER_ADDR | 0xa0000000);//should use un cached addr
			#ifdef BACKUP_USB_LOADER
				length=READ_USBUPG_BUFFER_SIZE;
			#endif
#else
				pBuff = (void *)(__MM_PVR_VOB_BUFFER_ADDR & 0x8fffffff);//MALLOC(length);//have included chunk_head info size
#endif
				if(pBuff != NULL)
				{
					//win_usbupg_msg_update(RS_USBUPG_READING_FILE);
					fileread_ret = usbupg_readfile(block_idx,file_idx,pBuff,length,(usbupg_prgrs_disp)win_usbupg_process_update);
					UU_PRINTF("%s-%d get %d from usbupg_readfile()\n",__FUNCTION__,__LINE__,fileread_ret);
					if(USBUPG_FILEREAD_NO_ERROR == fileread_ret)
					{
#ifdef _CAS9_CA_ENABLE_
						struct usbupg_ver_info ver_info;
						MEMSET(&ver_info, 0, sizeof(struct usbupg_ver_info));
#ifdef _M3503_
						win_usbupg_set_memory();
#endif
						usbupg_check(&ver_info,(UINT8 *)pBuff, (UINT32)length);
						if (  (ver_info.m_m_ver == 0) ||
							(ver_info.s_m_ver == 0) || 
							(ver_info.m_m_ver != ver_info.s_m_ver))
							goto UPDATE_FAIL;			
#else
	#if defined(_VMX_CA_STD_ENABLE_) || defined(_VMX_CA_ENABLE_)
						struct usbupg_ver_info ver_info;
						BOOL check_ret;

						UsbUpg_set_memory(pBuff,(UINT32)length);
						MEMSET(&ver_info, 0, sizeof(struct usbupg_ver_info));
						check_ret=usbupg_check(&ver_info,(UINT8 *)pBuff, (UINT32)length);
						if((check_ret!=TRUE)||(ver_info.m_m_ver != ver_info.s_m_ver))
							goto UPDATE_FAIL;			
#else
					/* For All code e.g product_glass_s3602.abs need to backup the HDCP from flash and 
						rewrite to all code image e.g. product_glass_s3602.abs						*/
						if (USBUPG_ALLCODE == usbupg_type)
						{							
							UINT32 chunk_id = 0;//HDCPKEY_CHUNK_ID;
#ifdef CI_PLUS_SUPPORT
							// CI+ FW upgrade:
							// step 1: we need to do FW signed check
							// step 2: we need to backup CI+ key
							if (FALSE == usbupg_allcode_check((UINT8 *)pBuff, (UINT32)length))
								goto UPDATE_FAIL;
							
							// backup CI+ Key
							chunk_id = CIPLUSKEY_CHUNK_ID;
							if (!backup_chunk_data(pBuff, length, chunk_id))
								goto UPDATE_FAIL;
#endif /* End of FW Signed Check & All Code Backup CI Plus Key Chunk */

#ifdef HDCP_IN_FLASH
							// backup HDCP Key which stored in flash
							chunk_id = HDCPKEY_CHUNK_ID;
                           	if (!backup_chunk_data(pBuff, length, chunk_id))
                                goto UPDATE_FAIL;
#endif/* End of all code backup HDCP Key chunk */


						}

						if (USBUPG_MAINCODE == usbupg_type)
						{
#ifdef CI_PLUS_SUPPORT			
							// maincode signature check
							if (FALSE == usbupg_maincode_check((UINT8 *)pBuff, (UINT32)length))
								goto UPDATE_FAIL;
#endif

//add for BUG46830
#ifdef _COMPRESS_LZO
                            //after compress len 
                            lzo_len1 = *(UINT32 *)(pBuff + CHUNK_HEADER_SIZE);
                            // before compress len 
                            lzo_len2 = *(UINT32 *)(pBuff + CHUNK_HEADER_SIZE+4);

                            //lzo: after compress len / before compress len may between 35~49
                            if( lzo_len1 == MAINCODE_ZIP_HEAD
                                ||lzo_len2 == 0 
                                ||lzo_len1*100 /lzo_len2  > 49 
                                || lzo_len1*100 /lzo_len2  < 35)
                            {
                            	UU_PRINTF("%s-%d got RS_MSG_UPGRADE_INVALID_FILE\n",__FUNCTION__,__LINE__);
                                popup_strid = RS_MSG_UPGRADE_INVALID_FILE;
                                goto ERROR_HANDLER;
                            }
                       
#else            
                            if (*(UINT32 *)(pBuff + CHUNK_HEADER_SIZE) != MAINCODE_ZIP_HEAD)
                            {
                                UU_PRINTF("%s-%d got RS_MSG_UPGRADE_INVALID_FILE\n",__FUNCTION__,__LINE__);
                                popup_strid = RS_MSG_UPGRADE_INVALID_FILE;
                                goto ERROR_HANDLER;
                            }
#endif                                                        
						}

						if (USBUPG_SEECODE == usbupg_type)
						{
#ifdef CI_PLUS_SUPPORT
							// seecode signature check
							if (FALSE == usbupg_seecode_check((UINT8 *)pBuff, (UINT32)length))
								goto UPDATE_FAIL;
#endif
						}
#endif						
#endif						
						win_compopup_init(WIN_POPUP_TYPE_OKNO);
						win_compopup_set_msg(NULL, NULL, RS_USBUPG_SURE_BURN_FLASH);
#if defined( SUPPORT_CAS7) || defined( SUPPORT_CAS9)						
						#ifndef SD_UI
						win_compopup_set_pos((OSD_MAX_WIDTH - 400)>>1,(OSD_MAX_HEIGHT - 168)>>1+1);
						#else
                        win_compopup_set_pos((OSD_MAX_WIDTH - 200)>>1,(OSD_MAX_HEIGHT - 86)>>1+1);
						#endif
#endif						
						choice = win_compopup_open_ext(&back_saved);
						if(choice == WIN_POP_CHOICE_YES)
						{
#if defined(_CAS9_CA_ENABLE_) || defined(_VMX_CA_STD_ENABLE_) || defined(_VMX_CA_ENABLE_)
						//only burn maincode and seecode
							win_usbupg_process_update(0);
							burnflash_ret = win_usb_burnflash(ver_info);						
#else
							win_usbupg_process_update(0);
							win_usbupg_msg_update(RS_OTA_BURNFLASH_DO_NOT_POWER_OFF);
							OSD_UpdateVscr(apVscr);
                            ge_io_ctrl(g_ge_dev, GE_IO_SET_SYNC_MODE, GE_SYNC_MODE_POOLING);
							osal_task_dispatch_off();
							burnflash_ret = usbupg_burnflash(block_idx,(UINT8 *)pBuff,(UINT32)length,(usbupg_prgrs_disp)win_usbupg_process_update);
							OSD_UpdateVscr(apVscr);
							osal_task_dispatch_on();
                            ge_io_ctrl(g_ge_dev, GE_IO_SET_SYNC_MODE, GE_SYNC_MODE_INTERRUPT);
#endif							
							if(burnflash_ret == TRUE)
							{
								popup_strid = RS_MSG_UPGRADE_SUCCESS;
								#if defined(_VMX_CA_STD_ENABLE_) || defined(_VMX_CA_ENABLE_)
								win_compopup_init(WIN_POPUP_TYPE_SMSG); 					   
								win_compopup_set_msg_ext(NULL, NULL, popup_strid);
								win_compopup_open_ext(&back_saved);
								osal_task_sleep(2000);
								win_compopup_smsg_restoreback();
						#endif	
								if((USBUPG_ALLCODE == usbupg_type)
									|| (USBUPG_MAINCODE == usbupg_type)
									/*|| (USBUPG_DFLTDB == usbupg_type)*/
                        #ifdef UPG_MEMCFG_SUPPORT        
                                    || (USBUPG_MEMCFG == usbupg_type)
                        #endif            
									)
								{
#ifdef BACKUP_TEMP_INFO
                                    save_swap_data(&system_config,sizeof(system_config));
#endif                                    
                        			key_pan_display("OFF ",4);
                        			osal_task_sleep(500);
                        			power_off_process(0);
								
				    #ifndef SUPPORT_VMX_STD
                                    if (USBUPG_ALLCODE == usbupg_type)
                                    {
                                        sys_data_factroy_init();
                    				    sys_data_set_factory_reset(TRUE);
                    				    sys_data_set_cur_chan_mode(TV_CHAN);
                                    }
				    #endif
					
                        			power_on_process();
									//sys_watchdog_reboot();
								}
								else if(USBUPG_LOGO == usbupg_type)
									api_show_menu_logo();
#ifdef HDCP_IN_FLASH
								
								else if(USBUPG_HDCPKEY == usbupg_type)
								{
									// delete programmed HDCP Key file. 								
									USBUPG_FILENODE filenode;	
									char dir_str[20];
													
									pMsel = &usbupg_filelist_sel;
									file_idx = OSD_GetMultiselSel(pMsel);									
									usbupg_get_filenode(&filenode,file_idx);	
									sprintf(dir_str,"/c/%s",filenode.upg_file_name);	
									fs_remove(dir_str);
									fs_sync("/c/"); 	
																	
									usbupg_create_filelist(block_idx,&usbupg_files_cnt);
									pMsel = &usbupg_filelist_sel;
									OSD_SetMultiselSel(pMsel, 0);
									OSD_SetMultiselCount(pMsel, (usbupg_files_cnt));
									OSD_DrawObject((POBJECT_HEAD)pMsel,C_UPDATE_ALL);							
									key_pan_display("OFF ",4);
								 	osal_task_sleep(500);
									power_off_process(0);
									power_on_process();
								
								}
#endif
							}
							else
							{
#if defined(_CAS9_CA_ENABLE_) || defined(_VMX_CA_ENABLE_) || defined(_VMX_CA_STD_ENABLE_)
								popup_strid = 0;
#else
								popup_strid = RS_MSG_UPGRADE_BURN_FLASH_ERROR;
#endif
							}
								
							//ret = PROC_LEAVE;
						}
						else
						{
							win_usbupg_process_update(0);
							popup_strid = 0;					
						}
					}
					else if(USBUPG_FIELREAD_ERROR_OVERFLOW == fileread_ret)
					{//if file size overflow chunk length,failure
						//mismatch files
						popup_strid =RS_MSG_UPGRADE_DATA_LARGE;
					}
					else
					{
UPDATE_FAIL:
						//error type:
						//USBUPG_FIELREAD_ERROR_READERROR
						//USBUPG_FIELREAD_ERROR_UNKOWN
						//USBUPG_FIELREAD_ERROR_NOFILE
						//popup_strid =RS_UDISK_ERROR;
                        UU_PRINTF("%s-%d got RS_MSG_UPGRADE_INVALID_FILE\n",__FUNCTION__,__LINE__);						
						popup_strid = RS_MSG_UPGRADE_INVALID_FILE;
						ret = PROC_LOOP;
					}
				}
ERROR_HANDLER:
				//free(pBuff);
			
				OSD_SetAttr(&usbupg_item_con1, C_ATTR_ACTIVE);
				OSD_SetAttr(&usbupg_item_con2, C_ATTR_ACTIVE);
				OSD_SetAttr(&usbupg_item_con3, C_ATTR_ACTIVE);
				OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con1, C_UPDATE_ALL);
				OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con2, C_UPDATE_ALL);
				OSD_TrackObject( (POBJECT_HEAD)&usbupg_item_con3, C_UPDATE_ALL);
				OSD_UpdateVscr(apVscr);
					
				if(popup_strid != 0)
				{
					win_usbupg_msg_update(popup_strid);
					
					win_compopup_init(WIN_POPUP_TYPE_SMSG);
					win_compopup_set_msg(NULL,NULL, popup_strid);
					win_compopup_open_ext(&back_saved);
					osal_task_sleep(2000);
					win_compopup_smsg_restoreback();
				}

				return ret;
			}
			break;
	}

	return ret;
}

static VACTION usbupg_con_keymap(POBJECT_HEAD pObj, UINT32 vkey)
{
	VACTION act;
	
	switch(vkey)
	{
	case V_KEY_UP:
		act = VACT_CURSOR_UP;
		break;
	case V_KEY_DOWN:
		act = VACT_CURSOR_DOWN;
		break;		
	case V_KEY_EXIT:
	case V_KEY_MENU:
	#ifdef _BUILD_USB_LOADER_
		act = VACT_PASS;
	#else
		act = VACT_CLOSE;
	#endif
		break;
	default:	
		act = VACT_PASS;
		break;
	}

	return act;
}

static PRESULT usbupg_con_callback(POBJECT_HEAD pObj, VEVENT event, UINT32 param1, UINT32 param2)
{
	PRESULT ret = PROC_PASS;
	CONTAINER* cont = (CONTAINER*)pObj;
	UINT8	id = OSD_GetObjID(pObj);

	switch(event)
	{
		case EVN_PRE_OPEN:
			//epg_release();
			wincom_open_title(pObj, RS_USBUPG_UPGRADE_BY_USB, 0);
			wincom_open_help(NULL, NULL, HELP_TYPE_RS232);
			OSD_SetProgressBarPos(&usbupg_bar_progress,(INT16)0);
			OSD_SetTextFieldContent(&usbupg_txt_progress, STRING_NUM_PERCENT, (UINT32)0);
			ret = win_usbupg_init();
		#if (defined(SUPPORT_VMX) || defined(SUPPORT_VMX_STD))
			vmx_cas_run_bc_task(FALSE);
		#endif
			break;			
		case EVN_POST_OPEN:
			system_state = SYS_STATE_USB_UPG;
			win_usbupg_msg_clear();
			break;
		case EVN_PRE_CLOSE:
          	/* Make OSD not flickering */
		    *((UINT32*)param2) &= ~C_CLOSE_CLRBACK_FLG;	
			break;
		case EVN_POST_CLOSE:
			system_state = SYS_STATE_NORMAL;
			wincom_close_title();
			wincom_close_help();
		#if (defined(SUPPORT_VMX) || defined(SUPPORT_VMX_STD))
			vmx_cas_run_bc_task(TRUE);
		#endif
			//epg_init(ap_send_epg_PF_update, ap_send_epg_sch_update, ap_send_epg_detail_update);
			break;
		case EVN_MSG_GOT:
			if(param1 ==  CTRL_MSG_SUBTYPE_CMD_EXIT)
			{
				ret = PROC_LEAVE;
			}
#if 1//ChengYu@20140221, for fast upgrade
			else if (param1 == CTRL_MSG_SUBTYPE_KEY)
			{
				switch(param2)
				{
					case V_KEY_FAST_UPG:
						system_state = SYS_STATE_USB_UPG;
						CHENGYU_PRINTF("Start fast upgrade\n");
						OSD_DrawObject((POBJECT_HEAD)&g_win_mainmenu, C_DRAW_SIGN_EVN_FLG | C_UPDATE_ALL);
						aov_fast_usbupg_start_proc(USBUPG_ALLCODE);
						ret=PROC_LEAVE;
						break;

					default:
						break;
				}
			}
#endif
#ifdef DISK_MANAGER_SUPPORT
			if (param1 == CTRL_MSG_SUBTYPE_CMD_STO && param2 == USB_STATUS_OVER)
			{
			#ifdef _BUILD_USB_LOADER_
				//update filelist
				MULTISEL *pMsel;
				
				usbupg_create_filelist(0,&usbupg_files_cnt);
				pMsel = &usbupg_filelist_sel;
				OSD_SetMultiselSel(pMsel, 0);
				OSD_SetMultiselCount(pMsel, (usbupg_files_cnt));
				OSD_DrawObject((POBJECT_HEAD)pMsel,C_UPDATE_ALL);
			#else
				// if disk used by usb upgrade detached, exit this menu
				struct statvfs buf;
				if (fs_statvfs("/c", &buf) != 0)
				{
					ret = PROC_LEAVE;
				}
			#endif
			}
#endif
			break;		
		default:
			break;
	}
	return ret;
}

static PRESULT win_usbupg_init(void)
{
	unsigned long block_id;
	RET_CODE block_ret,filelist_ret;
	MULTISEL *pMsel;
	UINT16 upg_show_count=0;
	usbupg_block_free();
	block_ret = usbupg_block_init(&usbupg_blocks_cnt);
	if(block_ret == RET_FAILURE)
	{
		return PROC_LEAVE;
	}
	
	usbupg_create_filelist(0,&usbupg_files_cnt);

	pMsel = &usbupg_sel_upgrade_type;
	OSD_SetMultiselSel(pMsel, 0);
    upg_show_count=usbupg_blocks_cnt;
#ifdef HDCP_IN_FLASH
    upg_show_count=upg_show_count-1;
#endif


    upg_show_count= upg_show_count- 2;/*except for bootloader,userdb*/

    OSD_SetMultiselCount(pMsel, upg_show_count);

	pMsel = &usbupg_filelist_sel;
	OSD_SetMultiselSel(pMsel, 0);
	OSD_SetMultiselCount(pMsel, usbupg_files_cnt);

    usbupg_txt_start.bX = TXTN_L_OF;

	return PROC_PASS;
}
#endif

#if 1//ChengYu@20140221, for fast upgrade
UINT8 aov_fast_usbupg_start_proc(USBUPG_BLOCK_TYPE block_type)
{
	UINT8 bID,back_saved;
	UINT16 block_idx,file_idx,popup_strid;
	INT32 vscr_idx,length,fileread_ret;
	char str_buff[20];
	void *pBuff;
	BOOL burnflash_ret;
	VACTION unact;
	PRESULT ret;
	PMULTISEL pMsel;
	lpVSCR apVscr;
	win_popup_choice_t choice;
	USBUPG_BLOCK_TYPE usbupg_type;

	RET_CODE block_ret;

	ret = PROC_PASS;

	win_usbupg_msg_clear();

	block_ret = usbupg_block_init(&usbupg_blocks_cnt);
	if(block_ret == RET_FAILURE)
	{
		usbupg_block_free();
		return PROC_LEAVE;
	}

	if (block_type==USBUPG_ALLCODE)
		block_idx = 0;
	else
		return 0;

	file_idx=0;

	usbupg_create_filelist(block_idx,&usbupg_files_cnt);

	if(usbupg_files_cnt == 0)
		return PROC_PASS;//ignore press msg when no file

	win_usbupg_process_update(0);
	vscr_idx = osal_task_get_current_id();
	apVscr = OSD_GetTaskVscr(vscr_idx);

	popup_strid = RS_USBUPG_ALERT_NOPLUG;
	
	win_compopup_init(WIN_POPUP_TYPE_SMSG);
	win_compopup_set_msg_ext(NULL,NULL, popup_strid);
	win_compopup_open_ext(&back_saved);
	osal_task_sleep(2000);
	win_compopup_smsg_restoreback();

	OSD_SetAttr(&usbupg_item_con1, C_ATTR_INACTIVE);
	OSD_SetAttr(&usbupg_item_con2, C_ATTR_INACTIVE);
	OSD_SetAttr(&usbupg_item_con3, C_ATTR_INACTIVE);
	OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con1, C_UPDATE_ALL);
	OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con2, C_UPDATE_ALL);
	OSD_DrawObject( (POBJECT_HEAD)&usbupg_item_con3, C_UPDATE_ALL);

	usbupg_get_blockinfo(block_idx,str_buff,&length);//get chunk length

	pBuff = (void *)(__MM_PVR_VOB_BUFFER_ADDR & 0x8fffffff);//MALLOC(length);//have included chunk_head info size
	if(pBuff != NULL)
	{
		usbupg_type = usbupg_get_block_type(block_idx);
		fileread_ret = usbupg_readfile(block_idx,file_idx,pBuff,length,(usbupg_prgrs_disp)win_usbupg_process_update);
		if(USBUPG_FILEREAD_NO_ERROR == fileread_ret)
		{
#if 0//Untraced code
#ifdef HDCP_IN_FLASH
			if (usbupg_type==USBUPG_ALLCODE)
			{
				/* For All code e.g product_glass_s3602.abs need to backup the HDCP from flash and
					rewrite to all code image e.g. product_glass_s3602.abs */
				UINT8 	*hdcp_internal_keys;
				CHUNK_HEADER hdcp_chuck_hdr;
				UINT32 hdcp_chuck_id = HDCPKEY_CHUNK_ID;

				if(sto_get_chunk_header(hdcp_chuck_id,&hdcp_chuck_hdr)!=0)
				{
					// read back the hdcp key from flash
					hdcp_internal_keys = (UINT8 *)MALLOC(sizeof(UINT8)*286);
					sto_get_data( (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0), hdcp_internal_keys,
														(UINT32)sto_chunk_goto(&hdcp_chuck_id,0xFFFFFFFF,1) + CHUNK_HEADER_SIZE, 286);		
					// restore back the hdcp key to all code image
					MEMCPY(pBuff +0xFE00+128 ,hdcp_internal_keys,286);
					FREE(hdcp_internal_keys);
				}
			}
#endif
#endif
			win_usbupg_process_update(0);
			win_usbupg_msg_update(RS_OTA_BURNFLASH_DO_NOT_POWER_OFF);
			OSD_UpdateVscr(apVscr);

			osal_task_dispatch_off();

			if (usbupg_type==USBUPG_ALLCODE)
			{
				burnflash_ret = usbupg_burnflash(block_idx,(UINT8 *)pBuff,(UINT32)length,(usbupg_prgrs_disp)win_usbupg_process_update);
				if(burnflash_ret == TRUE)
				{
					key_pan_display("donE",4);
					win_compopup_init(WIN_POPUP_TYPE_SMSG);
					//win_compopup_set_frame(200, 200, 200, 100);
					win_compopup_set_msg_ext("Software Upgrade Done! System Halt.",NULL,NULL);
					win_compopup_open();
					//halt system
					while(1);
				}
				else
				{
					popup_strid = RS_MSG_UPGRADE_BURN_FLASH_ERROR;
					key_pan_display("Err2",4);
					ret=PROC_LEAVE;
				}
			}

			OSD_UpdateVscr(apVscr);
			osal_task_dispatch_on();

		}
		else if(USBUPG_FIELREAD_ERROR_OVERFLOW == fileread_ret)
		{	//if file size overflow chunk length,failure
			//mismatch files
			popup_strid =RS_MSG_UPGRADE_DATA_LARGE;
			key_pan_display("Err3",4);
			ret = PROC_LOOP;
		}
		else
		{
			popup_strid = RS_MSG_UPGRADE_INVALID_FILE;
			key_pan_display("Err4",4);
			ret = PROC_LOOP;
		}
	}

	if(popup_strid != 0)
	{
		win_usbupg_msg_update(popup_strid);
		win_compopup_init(WIN_POPUP_TYPE_SMSG);
		win_compopup_set_msg_ext(NULL,NULL, popup_strid);
		win_compopup_open_ext(&back_saved);
		osal_task_sleep(2000);
		win_compopup_smsg_restoreback();
	}
	return ret;
}
#endif
